2015-03-05 2 views
76

Ich verwende oft Null propagierenden Operator in meinem Code, weil es mir mehr lesbaren Code gibt, speziell in langen Abfragen muss ich nicht jede einzelne Klasse, die verwendet wird, Null-überprüfen.Warum kann ich den Null-Propagierungsoperator nicht in Lambda-Ausdrücken verwenden?

Der folgende Code löst einen Kompilierungsfehler aus, bei dem wir in lambda keinen null-propagierenden Operator verwenden können.

var cnt = humans.AsQueryable().Count(a => a.House?[0].Price == 5000); 

Der Fehler:

Fehler CS8072 Ein Ausdruck Baum Lambda kann kein Null ausbreitende Operator enthalten.

C# Könnte den obigen Code leicht in den Code zum folgenden Code übersetzen, wenn wirklich nichts anderes möglich ist!

var cnt = humans.AsQueryable().Count(a => a.House != null && a.House[0].Price == 5000); 

Ich bin neugierig, warum C# nichts tut und einfach wirft ein Compiler-Fehler?

+3

'Foo? .Bar' ist nicht äquivalent zu' Foo! = Null? Foo.Bar: null, weil 'Foo' einmal mit dem Null-propagierenden Operator und zweimal mit dem Conditional ausgewertet wird, sodass die Übersetzung nicht in allen Fällen korrekt wäre. –

+2

Beachten Sie, dass es bei seinem Code für EF die Möglichkeit gibt, dass Sie den proprietären Nulloperator nicht wirklich benötigen, denn wenn eine Abfrage in einen SQL-Aufruf konvertiert wird, wirft SQL keine Nullen :-) – xanatos

+0

** NB: * * Es wäre auch nützlich, 'var q = von c in Kategorien zu schreiben join p in Produkte auf c gleich p.Kategorie in ps von p in ps.DefaultIfEmpty() wähle new {Category = c, ProductName = (p? .ProductName) ?? "(No products)"}; 'anstatt,' ProductName = (p == null) schreiben zu müssen? "(No products)": p.ProductName', weil EF den '? .' - Operator derzeit nicht unterstützt. – Matt

Antwort

58

Es ist kompliziert, da Expression Tree Lambdas (im Gegensatz zu Delegate Lambdas) von bereits vorhandenen LINQ-Providern interpretiert werden, die das Null-Propagieren noch nicht unterstützen.

zu einem bedingten Ausdruck Konvertieren ist nicht immer korrekt, da es mehrere Auswertungen sind, während sie mit ?. es zum Beispiel nur eine einzige Bewertung ist:

customer.Where(a => c.Increment()?.Name) // Written by the user 
customer.Where(a => c.Increment() == null ? null : c.Increment().Name) // Incorrectly interpreted by an old LINQ provider 

Sie in dem entsprechenden tiefer gehen können discussion on CodePlex wo drei Lösungen angeboten: NullPropagationExpression, ConditionalExpression & ein Hybrid

+12

Ich wäre sicherlich nicht überrascht, wenn bestimmte Abfrage-Provider es nicht unterstützen könnten, aber das ist kein Grund, die C# -Sprache nicht zu unterstützen. – Servy

+0

@Servy eigentlich denke ich, es ist ein guter Grund. Aber trotzdem wurde eine PR angeboten und noch nicht abgelehnt. – i3arnon

+10

Die Tatsache, dass * bestimmte * Abfrageprovider * dies noch nicht unterstützen *, ist kein Grund, * allen * Abfrageanbietern zu verbieten, * jemals * in der Lage zu sein, sie zu benutzen. – Servy