Wprowadzamy system i czasami otrzymujemy słynny wyjątek NullReferenceException
z komunikatem Object reference not set to an instance of an object
.
Jednak w metodzie, w której mamy prawie 20 obiektów, posiadanie dziennika, który mówi, że obiekt jest pusty, tak naprawdę w ogóle się nie przydaje. To tak, jakby powiedzieć, kiedy jesteś agentem bezpieczeństwa seminarium, że mężczyzna na 100 uczestników jest terrorystą. To naprawdę nie ma dla ciebie żadnego sensu. Powinieneś uzyskać więcej informacji, jeśli chcesz wykryć, który mężczyzna jest groźny.
Podobnie, jeśli chcemy usunąć błąd, musimy wiedzieć, który obiekt jest pusty.
Teraz coś mnie obsesję na punkcie od kilku miesięcy, a mianowicie:
Dlaczego .NET nie podaje nam nazwy, a przynajmniej rodzaju odwołania do obiektu, które jest puste? . Czy nie może zrozumieć typu z odbicia lub innego źródła?
Jakie są najlepsze praktyki, aby zrozumieć, który obiekt jest pusty? Czy zawsze powinniśmy ręcznie testować zerowanie obiektów w tych kontekstach i rejestrować wynik? Czy jest lepszy sposób?
Aktualizacja:
wyjątek The system cannot find the file specified
ma ten sam charakter. Nie możesz znaleźć pliku, dopóki nie zostanie dołączony do procesu i debugowany. Myślę, że tego rodzaju wyjątki mogą stać się bardziej inteligentne. Czy nie byłoby lepiej, gdyby .NET mógł nam powiedzieć c:\temp.txt doesn't exist.
zamiast tego ogólnego komunikatu? Jako programista głosuję na tak.
źródło
new
do tworzenia instancji klasy. Kiedy taka wskazówka naprawdę pomaga?Odpowiedzi:
NullReferenceException
Zasadzie mówi ci: robisz to źle. Nic dodać nic ująć. Wręcz przeciwnie, nie jest to pełne narzędzie do debugowania. W tym przypadku powiedziałbym, że robisz to źle, ponieważJestem wielkim fanem sprawdzania wszystkiego, zanim coś pójdzie nie tak i zapewniania dobrych informacji deweloperowi. W skrócie: napisz czeki za pomocą
ArgumentNullException
i polubień i napisz nazwisko. Oto próbka:Możesz także zajrzeć do kontraktów kodowych , ma dziwactwa, ale działa całkiem dobrze i oszczędza ci pisania.
źródło
I only say that checking every object to get sure that it's not null, is not a good method
Poważnie. To najlepsza metoda. I nie tylko zero, sprawdź każdy argument pod kątem rozsądnych wartości. Im wcześniej wykryjesz błędy, tym łatwiej będzie znaleźć przyczynę. Nie trzeba cofać się o kilka poziomów w śladzie stosu, aby znaleźć wywołanie wywołujące.Naprawdę powinien pokazywać dokładnie to, co próbujesz zadzwonić. To tak, jakby powiedzieć: „Jest problem. Musisz go naprawić. Wiem, co to jest. Nie powiem ci. Idź to rozgryźć” Trochę jak połowa odpowiedzi na temat przepełnienia stosu, jak na ironię.
Jak przydatne byłoby, na przykład, jeśli masz to ...
... Aby wejść do kodu, przejrzeć go i przekonać się, że to, co próbujesz wywołać,
null
jest w porządku, ale dlaczego nie po prostu podać nam pomocną dłoń?Zgadzam się, że zwykle przydatne jest przechodzenie przez kod, aby uzyskać odpowiedź (ponieważ prawdopodobnie dowiesz się więcej), ale często zaoszczędzono by dużo czasu i frustracji, gdyby
NullReferenceException
tekst był bardziej podobny do powyższego przykładu.Tylko mówię.
źródło
KeyNotFoundException
i wiele innych niedogodności ...Twój dziennik powinien zawierać ślad stosu - zwykle daje wskazówkę, która linia w metodzie ma problem. Może być konieczne, aby kompilacja wydania zawierała symbole PDB, abyś miał pomysł, w której linii wystąpił błąd.
To prawda, że nie pomoże ci w tym przypadku:
Zasada „ nie pytaj ” może pomóc uniknąć takiego kodu.
Co do tego, dlaczego informacje nie są zawarte, nie jestem pewien - podejrzewam, że przynajmniej w kompilacji debugowania, jeśli naprawdę chcieliby, mogliby to zrozumieć. Pomoże Ci zrobienie zrzutu awaryjnego i otwarcie w WinDBG.
źródło
Stworzono wyjątki jako narzędzie do sygnalizowania wyjątkowych, nie kończących się śmiercią warunków w łańcuchu połączeń. Oznacza to, że nie zostały one zaprojektowane jako narzędzie do debugowania.
Gdyby wyjątek wskaźnika zerowego był narzędziem do debugowania, przerywałby on wykonywanie programu natychmiast, umożliwiając debugerowi połączenie się, kierując go bezpośrednio na linię obciążającą. Dałoby to programiście wszystkie dostępne informacje kontekstowe. (Co jest mniej więcej tym, co robi Segfault ze względu na zerowy dostęp do wskaźnika w C, choć trochę z grubsza.)
Jednak wyjątek wskaźnika zerowego został zaprojektowany jako poprawny warunek działania, który może zostać wygenerowany i przechwycony podczas normalnego przepływu programu. W związku z tym należy wziąć pod uwagę względy wydajności. Każde dostosowanie komunikatu wyjątku wymaga tworzenia, łączenia i niszczenia obiektów łańcuchowych w czasie wykonywania. Jako taki, statyczny komunikat jest bezsprzecznie szybszy.
Nie twierdzę jednak, że środowiska wykonawczego nie można zaprogramować w sposób, który dałby nazwę obciążającego odwołania. Można to zrobić. Sprawiłoby to, że wyjątki byłyby nawet wolniejsze niż są. Jeśli komuś na to zależy, taka funkcja może nawet zostać przełączona, aby nie spowalniała kodu produkcyjnego, ale pozwalała na łatwiejsze debugowanie; ale z jakiegoś powodu nikt nie dbał wystarczająco.
źródło
Cromulent uderzył w gwóźdź w głowę, ale myślę, że jest też oczywisty punkt, że jeśli dostajesz
NullReferenceException
niezainicjowaną zmienną (zmienne). Argument, że masz około 20 obiektów przekazywanych do metody, nie może być uznany za złagodzenie: jako twórca fragmentu kodu musisz być odpowiedzialny za jego działania, w tym jego zgodność z resztą bazy kodu, ponieważ a także właściwe i prawidłowe wykorzystanie zmiennych itp.jest uciążliwy, żmudny i czasem nudny, ale nagrody na końcu są tego warte: w wielu przypadkach musiałem przeszukiwać pliki dzienników ważące kilka gigabajtów i prawie zawsze są pomocne. Jednak zanim przejdziesz do tego etapu, debugger może ci pomóc, a przed tym etapem dobre planowanie zaoszczędzi wiele bólu (i nie mam też na myśli w pełni skonstruowanego podejścia do twojego kodu: proste szkice i niektóre notatki mogą i będą być lepszym niż nic).
Jeśli chodzi o
Object reference not set to an instance of an object
kod, nie możemy zgadnąć, jakie wartości mogą nam się spodobać: to nasza praca jako programistów i oznacza to po prostu, że przekazałeś niezainicjowaną zmienną.źródło
Naucz się korzystać z debugera. To jest dokładnie to, do czego jest przeznaczony. Ustaw punkt przerwania dla danej metody i gotowe.
Wystarczy przejść przez kod i zobaczyć dokładnie, jakie są wartości wszystkich zmiennych w określonych punktach.
Edycja: Szczerze mówiąc jestem zszokowany, że nikt jeszcze nie wspomniał o użyciu debuggera.
źródło
Jeśli chcesz skorzystać z odpowiedzi @ stijn i umieścić w kodzie kody zerowe, ten fragment kodu powinien pomóc. Oto kilka informacji o fragmentach kodu . Po skonfigurowaniu wystarczy wpisać
argnull
, dwukrotnie nacisnąć klawisz Tab, a następnie wypełnić puste pole.źródło
nameof
taki fragmentthrow new ArgumentNullException(nameof($argument$))
kodu, który może mieć tę zaletę, że nie uwzględnia magicznych stałych, jest sprawdzany przez kompilator i działa lepiej z narzędziami do refaktoryzacji