Czy da się jakoś skrócić to stwierdzenie?
if (obj != null)
obj.SomeMethod();
ponieważ często to piszę i robi się to dość irytujące. Jedyne, co przychodzi mi do głowy, to zaimplementowanie wzorca Null Object , ale nie jest to to, co mogę zrobić za każdym razem i na pewno nie jest to rozwiązanie do skrócenia składni.
I podobny problem z wydarzeniami, gdzie
public event Func<string> MyEvent;
a następnie wywołaj
if (MyEvent != null)
MyEvent.Invoke();
Odpowiedzi:
Począwszy od C # 6, możesz po prostu użyć:
lub:
?.
Jest operatorem null rozmnożeniowego, oraz powoduje.Invoke()
się zwarcie przy operandzienull
. Dostęp do operandu jest możliwy tylko raz, więc nie ma ryzyka wystąpienia problemu „zmiany wartości między sprawdzaniem a wywołaniem”.===
Przed C # 6 nie: nie ma magii zerowej, z jednym wyjątkiem; metody rozszerzające - na przykład:
teraz to jest ważne:
W przypadku wydarzeń ma to tę zaletę, że usuwa również warunek wyścigu, tj. Nie potrzebujesz zmiennej tymczasowej. Więc normalnie potrzebujesz:
ale z:
możemy użyć po prostu:
źródło
?.
- w wersji VB14 i nowszychCo szukasz jest Null warunkowe (nie „koalescencyjny”) operator:
?.
. Jest dostępny od C # 6.Twój przykład to
obj?.SomeMethod();
. Jeśli obiekt ma wartość null, nic się nie dzieje. Gdy metoda ma argumenty, npobj?.SomeMethod(new Foo(), GetBar());
. Argumenty nie są obliczane, jeśliobj
jest zerowe, co ma znaczenie, jeśli ocena argumentów miałaby skutki uboczne.Łańcuch jest możliwy:
myObject?.Items?[0]?.DoSomething()
źródło
Szybka metoda rozszerzenia:
przykład:
lub alternatywnie:
przykład:
źródło
Zdarzenia można zainicjować z pustym domyślnym delegatem, który nigdy nie jest usuwany:
Nie jest konieczne sprawdzanie wartości zerowej.
[ Aktualizacja , dzięki Bevan za wskazanie tego]
Pamiętaj jednak o możliwym wpływie na wydajność. Szybki mikro-test porównawczy, który przeprowadziłem, wskazuje, że obsługa zdarzenia bez subskrybentów jest 2-3 razy wolniejsza przy użyciu wzorca „domyślny delegat”. (Na moim dwurdzeniowym laptopie 2,5 GHz oznacza to 279 ms: 785 ms na zebranie 50 milionów niezasubskrybowanych wydarzeń). W przypadku punktów aktywnych aplikacji może to być kwestia do rozważenia.
źródło
Tak, w C # 6.0 - https://msdn.microsoft.com/en-us/magazine/dn802602.aspx .
źródło
Ten artykuł Iana Griffithsa podaje dwa różne rozwiązania problemu, które, jak stwierdza, są zgrabnymi sztuczkami, których nie powinieneś używać.
źródło
Metoda przedłużania ceracji, taka jak ta sugerowana, nie rozwiązuje problemów związanych z warunkami wyścigu, ale raczej je ukrywa.
Jak stwierdzono, ten kod jest eleganckim odpowiednikiem rozwiązania z tymczasową zmienną, ale ...
Problem z obojgiem polega na tym, że możliwe jest wywołanie abonenta wydarzenia PO wypisaniu się z wydarzenia . Jest to możliwe, ponieważ anulowanie subskrypcji może nastąpić po skopiowaniu wystąpienia delegata do zmiennej tymczasowej (lub przekazaniu jako parametru w powyższej metodzie), ale przed wywołaniem delegata.
Generalnie zachowanie kodu klienta jest w takim przypadku nieprzewidywalne: stan komponentu nie mógł już pozwolić na obsługę powiadomienia o zdarzeniu. Możliwe jest napisanie kodu klienta w taki sposób, aby go obsłużyć, ale spowodowałoby to niepotrzebną odpowiedzialność po stronie klienta.
Jedynym znanym sposobem zapewnienia bezpieczeństwa wątków jest użycie instrukcji lock dla nadawcy zdarzenia. Gwarantuje to, że wszystkie subskrypcje \ unsubscriptions \ invocation są serializowane.
Aby być dokładniejszym, blokada powinna być zastosowana do tego samego obiektu synchronizacji, który jest używany w metodach dostępu do zdarzenia add \ remove, czyli domyślnie „this”.
źródło
Zgadzam się z odpowiedzią Kenny'ego Eliassona. Idź z metodami rozszerzającymi. Oto krótki przegląd metod rozszerzających i wymaganej metody IfNotNull.
Metody rozszerzające (metoda IfNotNull)
źródło
Może nie lepiej, ale moim zdaniem bardziej czytelne jest stworzenie metody rozszerzającej
źródło
return obj == null
znaczy. Co zwróciobj
tak , to myślę, żenull
metoda wrócitrue
.null
? Jestem prawie pewien, że to nie działa z własnymi metodami typu, więc wątpię, czy zadziałałoby również z metodami rozszerzającymi. Uważam, że najlepszym sposobem, aby sprawdzić, czy dany przedmiot jestnull
toobj is null
. Niestety, aby sprawdzić, czy obiekt nie jest nienull
wymaga owijania w nawiasach, co jest niekorzystne.Jest do tego mało znany operator null w języku C #, ??. Może być pomocny:
http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx
źródło