Chciałbym zapobiec dalszemu przetwarzaniu obiektu, jeśli jest on pusty.
W poniższym kodzie sprawdzam, czy obiekt jest pusty przez:
if (!data.Equals(null))
i
if (data != null)
Jednak mogę otrzymać NullReferenceException
na dataList.Add(data)
. Jeśli obiekt był zerowy, nigdy nie powinien był nawet wejść do if
-statement!
Dlatego pytam, czy to jest właściwy sposób sprawdzenia, czy obiekt jest pusty:
public List<Object> dataList;
public bool AddData(ref Object data)
bool success = false;
try
{
// I've also used "if (data != null)" which hasn't worked either
if (!data.Equals(null))
{
//NullReferenceException occurs here ...
dataList.Add(data);
success = doOtherStuff(data);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return success;
}
Jeśli jest to właściwy sposób sprawdzania, czy obiekt ma wartość null, co robię źle (jak mogę zapobiec dalszemu przetwarzaniu obiektu, aby uniknąć wyjątku NullReferenceException)?
c#
null
nullreferenceexception
deweloper
źródło
źródło
throw e;
versusthrow new Exception(e.ToString());
!= null
w swoich zerowych czekach..Equals
zawsze zgłasza wyjątek, jeśli obiekt jest pusty.throw e;
nie jest dużo lepszy.throw;
, z drugiej strony ...e.ToString()
wygeneruje ciąg znaków, który zawiera nie tylko komunikat o błędzie, ale także wszystkieInnerExceptions
i ślad stosu. To rodzaj bardzo grubego komunikatu wyjątku. Jeśli (słusznie!) Chcesz zachować te informacje i zachować je tam, gdzie należy, użyj po prostuthrow;
.Odpowiedzi:
To nie
data
taknull
, aledataList
.Musisz go utworzyć
Jeszcze lepiej: skoro to pole, zrób to
private
. A jeśli nic Cię nie powstrzyma, zrób to równieżreadonly
. Po prostu dobra praktyka.Na bok
Prawidłowy sposób sprawdzenia nieważności to
if(data != null)
. Ten rodzaj kontroli jest wszechobecny dla typów referencyjnych; nawetNullable<T>
zastępuje operator równości, aby był wygodniejszym sposobem wyrażanianullable.HasValue
podczas sprawdzania nieważności.Jeśli to zrobisz
if(!data.Equals(null))
, otrzymaszNullReferenceException
ifdata == null
. Co jest dość komiczne, ponieważ unikanie tego wyjątku było celem przede wszystkim.Robisz to również:
To zdecydowanie nie jest dobre. Mogę sobie wyobrazić, że umieściłeś go tam tylko po to, abyś mógł włamać się do debuggera, wciąż będąc w metodzie, w którym to przypadku zignoruj ten akapit. W przeciwnym razie nie wychwytuj wyjątków za darmo. A jeśli to zrobisz, rzuć je ponownie za pomocą just
throw;
.źródło
null != data
. Wprowadzenie stałej jako pierwszej zamienia literówkęnull = data
w błąd kompilatora, a nie niezamierzone przypisanie. (Działa również dla==
.)if (data = null)
występuje już błąd czasu kompilacji, więc nawet jeśli dotarcie tam zajęło dekady, tak naprawdę nie musimy już na to uważać. Nawet kompilatory C ++ z łatwością wygenerują ostrzeżenie o możliwym niezamierzonym przypisaniu tego kodu.w użyciu C #> 7.0
if (obj is null)
...To zignoruje dowolne == lub! = Zdefiniowane przez obiekt (chyba że oczywiście chcesz ich użyć ...)
Do użytku nie zerowego
if (obj is object)
(lubif (!(obj is null))
)źródło
obj is not null
)if (obj aint null)
:(if (obj is object)
C # 6 ma monadyczne sprawdzanie wartości zerowej :)
przed:
po:
źródło
result = myObject == null ? null : myObject.SomeProperty
a twój przykład dał mi wskazówkę do napisaniaresult = myObject?.SomeProperty
. Człowiek!! To podstępne. Nadal uwielbiam kodować ...Twoja dataList ma wartość NULL, ponieważ nie została utworzona instancja, sądząc po opublikowanym kodzie.
Próbować:
}
źródło
[Edytowane w celu odzwierciedlenia podpowiedzi @ kelton52]
Najprostszy sposób to zrobić
object.ReferenceEquals(null, data)
Ponieważ
(null==data)
NIE gwarantuje się działania:Produkuje:
źródło
Nie, powinieneś używać
!=
. Jeślidata
faktycznie jest zerowy, to twój program po prostu zawiesi sięNullReferenceException
w wyniku próby wywołaniaEquals
metodynull
. Pamiętaj również, że jeśli chcesz sprawdzić równość referencji, powinieneś użyć tejObject.ReferenceEquals
metody, ponieważ nigdy nie wiesz, jakEquals
została zaimplementowana.Twój program ulega awarii, ponieważ
dataList
jest zerowy, ponieważ nigdy go nie inicjujesz.źródło
Problem w tym przypadku nie
data
polega na tym, że jest zerowy. To, żedataList
sam jest null.W miejscu, w którym deklarujesz
dataList
, powinieneś utworzyć nowyList
obiekt i przypisać go do zmiennej.źródło
Oprócz odpowiedzi @Jose Ortega , jej lepsza metoda rozszerzenia wykorzystania
I użyj
IsNull
metody dla wszystkich obiektów, takich jak:źródło
return T == null ? true : false;
nie tylkoreturn T == null;
?Od wersji C # 8 możesz użyć wzorca właściwości „pusta” (z dopasowaniem wzorca ), aby upewnić się, że obiekt nie ma wartości zerowej:
To podejście oznacza „ jeśli obiekt odwołuje się do wystąpienia czegoś ” (tzn. Nie ma wartości null).
Możesz to traktować jako przeciwieństwo:
if (obj is null)...
. która zwróci true, gdy obiekt nie odwołuje się do instancji czegoś.Aby uzyskać więcej informacji o wzorach w C # 8.0, przeczytaj tutaj .
źródło
Od wersji C # 9 możesz to zrobić
Do użytku nie zerowego
Jeśli musisz zastąpić to zachowanie, użyj
==
i!=
odpowiednio.źródło
Jeffrey L Whitledge ma rację. Sam obiekt `dataList´ ma wartość NULL.
Istnieje również inny problem z twoim kodem: używasz słowa kluczowego ref, co oznacza, że dane argumentu nie mogą mieć wartości null! MSDN mówi:
Nie jest również dobrym pomysłem stosowanie rodzajów ogólnych z typem „Obiekt”. Leki ogólne powinny unikać boksowania / rozpakowywania, a także zapewniać bezpieczeństwo typu. Jeśli chcesz mieć wspólny typ, uczyń swoją metodę ogólną. Wreszcie twój kod powinien wyglądać następująco:
źródło
Jak inni już wspomniano, nie jest to
data
jednak dość prawdopodobne,dataList
że jestnull
. W dodatku...catch
-throw
jest antypatternem, który prawie zawsze sprawia, że chcę wymiotować za każdym razem, gdy go widzę. Wyobraź sobie, że coś idzie nie tak głęboko w czymś, codoOtherStuff()
wzywa. Wszystko wrócisz toException
przedmiot, rzucony nathrow
INAddData()
. Brak śladu stosu, brak informacji o wywołaniu, brak stanu, nic, co wskazywałoby na prawdziwe źródło problemu, chyba że wejdziesz i przełączysz debugger na przerwanie zgłoszonego wyjątku zamiast wyjątku nieobsługiwanego. Jeśli wychwytujesz wyjątek i po prostu ponownie go rzucasz w jakikolwiek sposób , szczególnie jeśli kod w bloku try jest w jakikolwiek sposób nieistotny, zrób sobie (i swoim kolegom, obecnym i przyszłym) przysługę i wyrzuć całośćtry
-catch
blok . Zgoda,throw;
jest lepsze niż alternatywy, ale wciąż dajesz sobie (lub ktokolwiek inny próbuje naprawić błąd w kodzie) zupełnie niepotrzebne bóle głowy. Nie oznacza to, że rzut próbny jest koniecznie zły sam w sobie, o ile zrobisz coś istotnego z rzuconym obiektem wyjątku do bloku catch.Potem są potencjalne problemy z łapaniem
Exception
, ale to inna sprawa, zwłaszcza, że w tym konkretnym przypadku rzucasz wyjątek.Kolejną rzeczą, która wydaje mi się bardziej niż trochę niebezpieczna, jest to, że
data
może potencjalnie zmienić wartość podczas wykonywania funkcji, ponieważ przechodzisz przez referencję. Kontrola zerowa może więc zakończyć się pomyślnie, ale zanim kod zacznie cokolwiek robić z wartością, zostanie zmieniona - być może nanull
. Nie jestem pewien, czy jest to problem, czy nie (może nie być), ale wydaje się, że warto na niego uważać.źródło
posługiwać się:
Zastosowanie warunkowe:
Aktualizacja (inna metoda) zaktualizowana 31.08.2017. Dziękuję za komentarz.
źródło
cond ? true : false;
jest całkowicie równoważne z justcond
. To nic nie dodaje.return T == null;
również zwraca wartość logiczną!return T == null ? true : false;
prostu użyćreturn T == null;
.Za każdym razem, gdy tworzysz obiekty klasy, musisz sprawdzić, czy obiekt jest pusty, czy nie, używając poniższego kodu.
Przykład: obiekt1 jest obiektem klasy
źródło
Właśnie zastosowałem metodę, którą zwykle stosujemy w skrypcie Java. Aby przekonwertować obiekt na ciąg, a następnie sprawdź, czy są one puste.
źródło
Zrobiłem prostszy (pozytywny sposób) i wydaje się, że działa dobrze.
Ponieważ jakikolwiek „obiekt” jest co najmniej przedmiotem
źródło