5

Der elvis-Operator, auch bekannt als Null-Conditional-Operator, ist massiv cool.Elvis-Operator in einer Casting-Aufrufkette

In LINQ-Abfragen funktioniert es gut zusammen mit dem Null-Koaleszenz "??" Operator.

Somedata.Where(dt=>(dt?.Inner?.InnerMost?.Include=="Yes")??false); 

Aber was tun Sie, wenn Sie die Zwischenwerte werfen müssen?

Für einen Link in der Kette funktioniert es gut.

Somedata.Where(dt=>(
    ((InnerClass)dt?.Inner) 
    ?.InnerMost)?.Include=="Yes") 
    ??false); 

Aber mit zusätzlichen notwendigen Casts werden der Cast und der Aufruf "auseinander getrieben".

Vermasselt wahrscheinlich die Klammer mehr als einmal hier, aber ich hoffe, Sie bekommen die Idee.

Obwohl diese "Trainwreck" -Aufrufskette ein Code-Geruch ist, gibt es einen expressiveren Weg, dies zu tun, um Prägnanz und Klarheit zu verbessern?

+4

Dies ist ein wenig besser aussehen '((((dt als InnerClass)?. Inner) als InnerMostClass)?. InnerMost) ?. Include == "Yes")) ?? false ' – Andrey

+1

Ich kann nichts besseres als @Andrey Lösung denken, andere dann, natürlich nicht diese Art von Aussagen in erster Linie schreiben. Es macht Spaß, so viel Funktionalität wie möglich in so wenige Zeilen wie möglich zu pressen, aber dafür gibt es Code-Golf. Für Code, den Benutzer pflegen müssen, ist meine Rolle des Daumens, dass, wenn Sie nicht auf einen Blick sagen können, was ein Lambda tut, sollte es eine benannte Funktion sein ... gute Frage aber ... – pseudoDust

+1

Ich bin mit pseudoDust : Ich würde diese Aussage verwerfen. Die Menge an Gehirnkraft, die Sie aufwenden müssen, um herauszufinden, was es macht, ist ein Code-Geruch. Außerdem wäre ich besorgt darüber, in welcher Situation ich mich befand, wo ich einen Elternteil und seine Kinder werfen muss, von denen alle null sein können. – CptCoathanger

Antwort

1

Sie halten können Chaining und die Klammer zu verhindern, indem eine sehr einfache Erweiterung Methode:

dt?.Inner.As<InnerClass>()?.InnerMost.As<InnerMostClass>()?.Include == "Yes" 

Mit der Erweiterung Methode wie folgt definiert:

public static class ObjectExtensions 
{ 
    public static T As<T>(this object obj) where T : class 
    { 
     return obj as T; 
    } 
} 
+0

Interessant. Schade, dass wir dort "Objekt" und ": Klasse" Beschränkung verwenden müssen. Es wäre cool, wenn wir angeben könnten, dass TInput eine Schnittstelle oder Basisklasse von TResult sein müsste, um eine Kompilierzeitüberprüfung zu erhalten. Aber in C# müssen TInput und TResult explizite Typparameter sein. Das Optimum wäre, dass wir nur TResult angeben, aber TInput als abgeleitet betrachten. Ich nehme an, es gibt F # in meiner Zukunft ..... außer ich vergesse etwas. – Tormod