5

Operator elvis, znany również jako operator null-conditional, jest bardzo fajny.Operator Elvisa w łańcuchu wywoływania odlewania

W zapytaniach LINQ działa świetnie w połączeniu z koalescencyjnym "??" operator.

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

Ale co zrobić, gdy trzeba rzucić wartości pośrednie?

Dla jednego ogniwa w łańcuchu działa dobrze.

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

Ale z dodatkowymi niezbędnymi rzutami obsada i inwokacja są "od siebie oddalone".

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

Prawdopodobnie zawiodłem tu nawias wiele razy, ale mam nadzieję, że wpadniesz na ten pomysł.

Chociaż ten łańcuch wywoływania "wraku pociągu" jest zapachem kodu, czy istnieje bardziej ekspresyjny sposób na to, aby poprawić jego zwięzłość i wyrazistość?

+4

To może wyglądać trochę lepiej '((((dt jako InnerClass). Inner) jako InnerMostClass). InnerMost). Include == "Yes"))? false ' – Andrey

+1

Nie mogę wymyślić niczego lepszego niż rozwiązanie @Andrey, inne, oczywiście, nie pisząc tego typu stwierdzeń w pierwszej kolejności. Fajnie jest spróbować i wycisnąć jak najwięcej funkcjonalności w tak niewielu linijkach, jak to tylko możliwe, ale jest do tego kodowy golf. Dla kodu, który ludzie muszą utrzymywać, moja rola kciuka polega na tym, że jeśli nie potrafisz w mgnieniu oka stwierdzić, co robi lambda, powinna to być nazwana funkcja ... dobre pytanie ... – pseudoDust

+1

Jestem z pseudoDustem : Zrzuciłbym to oświadczenie. Ilość energii mózgowej, którą musisz wydać, próbując ustalić, co robi, to zapach kodu. Poza tym martwiłbym się, w jakiej sytuacji znalazłem się w sytuacji, w której muszę rzucić rodzica i jego dzieci, z których każda może być zerowa. – CptCoathanger

Odpowiedz

1

można przechowywać łańcuchowym i zapobiec nawias za pomocą bardzo prostą metodę rozszerzenia:

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

Z metodę rozszerzenia zdefiniowane następująco:

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

Interesujące. Szkoda, że ​​musimy użyć "obiektu" tam i "klasy" powściągliwości. Byłoby fajnie, gdybyśmy mogli wskazać, że TInput musiałby być interfejsem lub klasą bazową TResulta, aby uzyskać trochę czasu kompilacji. Ale w języku C# wymagałoby to, aby zarówno TInput, jak i TResult były jawnymi parametrami typu. Optymalny byłby dla nas tylko stwierdzenie TResult, ale pozostawiając TInput do wywnioskowania. Przypuszczam, że w mojej przyszłości jest F #, chyba że coś zapomnę. – Tormod