Czy istnieje lepszy sposób na wykonanie następujących czynności:
Potrzebuję sprawdzenia, czy w pliku nie występuje null. Nagłówki przed kontynuowaniem pętli
if (file.Headers != null)
{
foreach (var h in file.Headers)
{
//set lots of properties & some other stuff
}
}
Krótko mówiąc, pisanie foreach wewnątrz if wygląda trochę brzydko ze względu na poziom wcięć występujących w moim kodzie.
To coś, co by się liczyło
foreach(var h in (file.Headers != null))
{
//do stuff
}
możliwy?
Odpowiedzi:
Jako niewielki kosmetyczny dodatek do sugestii Rune, możesz stworzyć własną metodę rozszerzenia:
public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source) { return source ?? Enumerable.Empty<T>(); }
Następnie możesz napisać:
foreach (var header in file.Headers.OrEmptyIfNull()) { }
Zmień nazwę według gustu :)
źródło
Zakładając, że typ elementów w file.Headers to T, możesz to zrobić
foreach(var header in file.Headers ?? Enumerable.Empty<T>()){ //do stuff }
spowoduje to utworzenie pustego wyliczalnego T, jeśli file.Headers ma wartość null. Jeśli typ pliku jest typem, którego jesteś właścicielem, rozważyłbym jednak zmianę metody pobierania
Headers
.null
jest wartością nieznane, więc jeśli to możliwe, zamiast używać null jako „Wiem, że nie ma elementów”, gdy null faktycznie (/ pierwotnie) powinno być interpretowane jako „Nie wiem, czy są jakieś elementy” użyj pustego zestawu, aby pokazać że wiesz, że w zestawie nie ma żadnych elementów. Byłoby to również bardziej SUCHE, ponieważ nie będziesz musiał tak często sprawdzać zerowej wartości.EDYTUJ jako kontynuację sugestii Jonsa, możesz również utworzyć metodę rozszerzenia zmieniającą powyższy kod na
foreach(var header in file.Headers.OrEmptyIfNull()){ //do stuff }
W przypadku, gdy nie możesz zmienić metody pobierającej, byłby to mój własny preferowany sposób, ponieważ wyraźniej wyraża zamiar, nadając operacji nazwę (OrEmptyIfNull)
Wspomniana powyżej metoda rozszerzenia może uniemożliwić wykrywanie niektórych optymalizacji przez optymalizator. W szczególności można wyeliminować te, które są związane z IList przy użyciu przeciążania metod
public static IList<T> OrEmptyIfNull<T>(this IList<T> source) { return source ?? Array.Empty<T>(); }
źródło
null
) degeneracji całej pętli do LCDIEnumerable<T>
(jak przy użyciu ?? by), b) wymagały dodania metody rozszerzenia do każdego projektu lub c) wymagały unikanianull
IEnumerables
(Pffft! Puh-LEAZE! SMH.) na początku (bonull
oznacza N / A, podczas gdy pusta lista oznacza, że ma zastosowanie, ale obecnie jest, no cóż, puste !, tj. pracownik może mieć prowizje, które nie dotyczą elementów niesprzedażnych lub są puste w przypadku sprzedaży, jeśli nie zarobił).IEnumerable
bardziej restrykcyjne niżforeach
wymagania, ale mniej restrykcyjne niż wymaganieList<T>
w odpowiedzi, do której prowadzi łącze. Które mają taki sam spadek wydajności, jak testowanie, czy wyliczalny jest pusty.List<T>
.Szczerze mówiąc, radzę: po prostu zassać
null
test.null
Test jest tylko Abrfalse
lubbrfalse.s
; wszystko inne będzie obejmować znacznie więcej pracy (testy, zadania, dodatkowe wywołania metod, niepotrzebneGetEnumerator()
,MoveNext()
,Dispose()
na iteracyjnej, etc).if
Badanie jest proste, oczywiste i skuteczny.źródło
„jeśli” przed iteracją jest w porządku, niewiele z tych „ładnych” semantyki może sprawić, że kod będzie mniej czytelny.
tak czy inaczej, jeśli wcięcie ci przeszkadza, możesz zmienić if, aby sprawdzić:
if(file.Headers == null) return;
a do pętli foreach dojdziesz tylko wtedy, gdy we właściwości headers znajduje się wartość true.
Inną opcją, o której mogę pomyśleć, jest użycie operatora koalescencji zerowej wewnątrz pętli foreach i całkowite uniknięcie sprawdzania wartości null. próba:
List<int> collection = new List<int>(); collection = null; foreach (var i in collection ?? Enumerable.Empty<int>()) { //your code here }
(zastąp kolekcję swoim prawdziwym obiektem / typem)
źródło
Korzystanie z operatora warunkowego o wartości null i ForEach (), które działają szybciej niż standardowa pętla foreach.
Musisz jednak przesłać kolekcję do listy.
listOfItems?.ForEach(item => // ... );
źródło
Używam ładnej, małej metody rozszerzenia dla tych scenariuszy:
public static class Extensions { public static IList<T> EnsureNotNull<T>(this IList<T> list) { return list ?? new List<T>(); } }
Biorąc pod uwagę, że nagłówki są listą typów, możesz wykonać następujące czynności:
foreach(var h in (file.Headers.EnsureNotNull())) { //do stuff }
źródło
??
operatora i skrócić instrukcję powrotu doreturn list ?? new List<T>;
null
twojej próbkifile.Headers.EnsureNotNull() != null
nie jest potrzebny, a nawet jest zły?W niektórych przypadkach wolałbym nieco inny, ogólny wariant, zakładając, że z reguły domyślne konstruktory kolekcji zwracają puste wystąpienia.
Lepiej byłoby nazwać tę metodę
NewIfDefault
. Może być przydatny nie tylko w przypadku kolekcji, więc ograniczenie typuIEnumerable<T>
może być zbędne.public static TCollection EmptyIfDefault<TCollection, T>(this TCollection collection) where TCollection: class, IEnumerable<T>, new() { return collection ?? new TCollection(); }
źródło