2016-04-20 21 views
0

Ich habe diese LINQ-Anweisung, die Null zurückgibt, wenn die Sequenz leer ist. Ich weise das Ergebnis einem Nullwert zu DateTime. Später überprüfe ich, ob die DateTime.HasValue Eigenschaft und ReSharper mir sagt, dass der Ausdruck immer wahr ist.Warum sagt mir ReSharper, dass mein Ausdruck immer wahr ist?

DateTime? latestUploadDateInBLSO = Documents.Where(d => d.DocumentLinkId == documentLinkId && 
                    d.UploadedInStage.StageNumber == 6 && 
                    d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId) 
                    .Select(d => d.UploadedOnDate) 
                    .DefaultIfEmpty() 
                    .Max(); 

if (latestUploadDateInBLSO.HasValue) { // <-- Says this is always true 
        Documents.Single(d => d.DocumentLinkId == documentLinkId && 
              d.UploadedOnDate == latestUploadDateInBLSO && 
              d.UploadedInStage.StageNumber == 6 && 
              d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId).IsLatestVersion = true; 
       } 

Da latestUploadDateInBLSO kann null sein, wie ist das Ausdruck immer wahr?

+3

Gibt es einen Code zwischen diesen beiden Aussagen? Was ist der Typ von 'UploadedOnDate'? –

+0

Nein, sie sind fortlaufend – Legion

+3

Was ist der Typ von 'UploadedOnDate'? –

Antwort

5

Da UploadedOnDate nicht nullfähig ist, wird das Ergebnis immer ein DateTime-Wert und niemals null sein. Wenn die Liste leer ist, erhalten Sie default(DateTime), also DateTime.MinValue.

Wenn Sie möchten, dass null zurückgegeben wird, müssen Sie Ihre UploadedOnDate in DateTime? umwandeln. Sie können DefaultIfEmpty gemäß the docsMax weglassen null für eine leere Sequenz, wenn der Typ nullfähig ist.

DateTime? latestUploadDateInBLSO = Documents 
    .Where(d => d.DocumentLinkId == documentLinkId && d.UploadedInStage.StageNumber == 6 && d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId) 
    .Select(d => (DateTime?)d.UploadedOnDate) 
    .Max(); 
+0

Ich hatte den Eindruck, dass 'Max()' eine Ausnahme auslöst, wenn sie null ist. Ich versuche im Grunde, den Maximalwert zu erhalten, wenn vorhanden, und Null, wenn die Sequenz leer ist. – Legion

+0

@Legion Eine leere Sequenz ist nicht dasselbe wie eine Null oder eine Folge von Nullen. 'Max()' kann nicht mit leeren Sequenzen von nicht nullbaren Elementen umgehen. Es kann Nullen behandeln. – GSerg

+0

Sie können es versuchen. [diese Geige] (https://dotnetfiddle.net/1lVxDg) nicht. –

2

Es ist wegen des Anrufs DefaultIfEmpty mit einer Folge von Nicht-Nullable-Elementen kombiniert (DateTime) - Sie sagen, wenn die Sammlung von den Where und Select zurückgekehrt ist leer, stattdessen zurückgeben eine Sammlung mit einer einzigen notleidenden DateTime innerhalb es, so wird es nie zurückkehren null.

Hier ist eine kleine Probe mit der Ausgabe von LINQPad:

List<DateTime> l = new List<DateTime>(); 
DateTime x = l.DefaultIfEmpty().Max(); 
x.Dump(); 

var y = new DateTime(); 
y.Dump(); 

l.DefaultIfEmpty().Dump(); 

enter image description here

+1

Es ist nicht * nur * wegen des Aufrufs 'DefaultIfEmpty', sondern wegen des Aufrufs 'DefaultIfEmpty' für eine nicht nullfähige Eigenschaft. – GSerg

+0

@GSerg fair point, bearbeitet –

+0

Ich versuche wirklich nur eine Null-Referenz Ausnahme mit Max zu vermeiden, wenn die Sequenz leer ist. Wenn ich "UploadedOnDate" auf "DateTime" stelle, bin ich nicht wieder da, wo ich angefangen habe? – Legion

3

Wenn uploadedOnDate auch von Datetime-Typ ist, dann ist es nicht NULL. Der Standardwert für DateTime entspricht DateTime.MinValue. Aus diesem Grund hat Ihr Nullwert immer einen Wert. Wenn Sie dies ändern möchten, müssen Sie explizit über DefaultIfEmpty sagen und NULL als Standardwert zurückgeben.

1

DefaultIfEmpty initialisiert wahrscheinlich Ihr DateTime-Objekt auf seinen Standardwert DateTime.MinValue, so dass es niemals null ist und HasValue daher immer true zurückgibt.

Verwandte Themen