2014-04-10 13 views
5

Używam tego rozwiązania zrobić przykuty zerową kontrolę w moim koduelegancki sposób zrobić Chained Null Sprawdza

Cleaner way to do a null check in C#?

Właśnie zastanawiałem cant robimy to w ten sposób.

bool returnValue = Helper.IsNull(nullPerson.contact.address.city); 

Czy nie byłoby to jeszcze czystsze?

Próbowałem pisać taką ogólną funkcję

public static bool IsNull<T>(this T rootObj) 
{ 
    var visitor = new IsNullExpressionVisitor(); 
    //... 
    //... 
} 

ale potem utknąłem w jaki sposób dokonać ekspresji z tego rootObject.

+2

nie sądzę, że istnieje jakikolwiek sposób to zrobić z tym podpisem. Ale możesz mieć więcej szczęścia, przechodząc w lambda. w następujący sposób: IsNull (() => nullPerson.contact.address.city). –

+0

W zależności od używanej wersji dotnetu można użyć klasy statycznej Umowa http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.contract.aspx – JCorriveau

+0

Czego można się spodziewać jako wartości zwracanej w łańcuchu 'nullPerson.contact.address.city', jeśli istnieje wartość pusta? – samy

Odpowiedz

4

Jednym ze sposobów podejścia do tego (choć nadal nieco niepewny) jest użycie a construct that's sometimes called a "Maybe" monad.

Korzystanie że kod stanie się coś takiego (który może lub nie może preferować!):

string city = nullPerson.With(x => x.address) 
         .With(x => x.city); 

jednak radować ponieważ C# is getting the "Safe Navigation" operator (?.) in the next version*.

Z tego nowego operatora ?., kod będzie wyglądać tak:

city = nullPerson?.address?.city; 

(* Podobno ...)

+0

+1 dla bezpiecznego operatora nawigacji :) – samy

+0

Niestety, nie jestem przekonany, czy ta funkcja rzeczywiście będzie w C# 6 ... może C# 7? –

+0

Czy nie ma gdzieś użytkownika, gdzie możemy naciskać na operatora? – samy

1

Po przeczytaniu manyquestions próbując rozwiązać ten sam problem, wychodzę na kończynę i mówię, że jest obecnie nie można stworzyć naprawdę eleganckiego przykutego czeku zerowego, gdzie elegancki oznaczałoby nie dodawanie pośrednictwa do każdego składnika łańcuch.

Owijanie łańcuch w ocenie lambda jest chyba najmniej straszny sposób to zrobić w tym czasie, i to działa tylko w:

CheckNull<string>(() => nullPerson.contact.address.city); 

T CheckNull<T>(Func<T> f) { try { return f(); } catch { return default(T); } } 

wolałbym zachęcić do wypróbowania i postępuj Law of Demeter mówi, że twój obiekt nie powinien wiedzieć o wewnętrznych działaniach obiektów, z którymi pracuje i prosi ich, aby zwracali wartość w dowolny sposób, zamiast schodzić z drzewa klas.

+0

Zła praktyka to używanie catch poza błędami przetwarzania =) Ale twoja metoda bardzo bliska mojemu rozwiązaniu: http://stackoverflow.com/a/34086283/4711853 –

0

Nie, nie ma. Wszystkie istniejące rozwiązania, które widziałem, są znacznie bardziej przerażające niż problem. Wiele sprytnych rozwiązań tylko utrudnia innym zrozumienie, co robi kod.

Sytuacja jest taka, że ​​chcesz zrobić coś takiego:

city = selectedPerson.Contact.Address.City; 

Co można zrobić, to hermetyzacji kontrole w nieruchomości

City SelectedCity 
{ 
    get 
    { 
     if (selectedPerson == null || selectedPerson.Contact == null || selectedPerson.Contact.Address == null) 
      return null; 
     return selectedPerson.Contact.Address.City; 
    } 
} 

Po wszystkim przez samą naturę chcąc aby uzyskać dostęp do tego długiego łańcucha nieruchomości, masz pojęcie wybranego miasta. Kod nie jest elegancki, ale przynajmniej jest ukryty w jednym miejscu, a każdy, kto go czyta, może natychmiast zrozumieć, czym jest "SelectedCity".

0

Sprawdź moją odpowiedź tutaj

https://stackoverflow.com/a/34086283/4711853

można po prostu napisać małą metodę rozszerzenia, które sobie pozwolić na pisanie przykuty lambda tak:

var val = instance.DefaultOrValue (x => x .SecondInstance) .DefaultOrValue (x => x.ThirdInstance) .DefaultOrValue (x => x.Value);

można nazwać tę metodę shortier

Powiązane problemy