Co to jest NullReferenceException i jak to naprawić?

Odpowiedzi na to pytanie są wysiłkiem społeczności. Edytuj istniejące odpowiedzi, aby poprawić ten post. Obecnie nie przyjmuje nowych odpowiedzi ani interakcji.

Mam jakiś kod i po wykonaniu, rzuca NullReferenceException, powiedzenie:

Odniesienie do obiektu nie jest ustawione na instancję obiektu.

Co to oznacza i co mogę zrobić, aby naprawić ten błąd?

Author: John Saunders, 2011-01-11

28 answers

Jaka jest przyczyna?

Bottom Line

Próbujesz użyć czegoś, co jest null (lub Nothing w VB.NET oznacza to, że albo ustawiasz go na null, albo nigdy nie ustawiasz go na nic.

Jak Wszystko inne, null zostaje pominięta. Jeśli jest null w metodzie "a", może być tak, że metoda " B " przeszła a null do metody "a".

null może mieć różne znaczenia:

  1. zmienne obiektu, które są niezawinione i stąd wskazywać na nic. w tym przypadku, jeśli uzyskasz dostęp do Właściwości lub metod takich obiektów, spowoduje to NullReferenceException.
  2. deweloper używa null celowo, aby wskazać, że nie ma znaczącej wartości dostępnej. zauważ, że C# ma pojęcie nullable datatypes dla zmiennych ( jak tabele bazy danych mogą mieć nullable fields) - możesz przypisać do nich null, aby wskazać, że nie ma w nim wartości, na przykład int? a = null;, gdzie znak zapytania wskazuje, że dozwolone jest przechowywanie null W Zmiennej a. Możesz to sprawdzić za pomocą if (a.HasValue) {...} lub if (a==null) {...}. Zmienne Nullable, takie jak a ten przykład, pozwalają na dostęp do wartości poprzez a.Value jawnie, lub po prostu jako normalne przez a.
    Uwaga, że dostęp do niej przez a.Value rzuca InvalidOperationException zamiast NullReferenceException jeśli a jest null - powinieneś wcześniej sprawdzić, tzn. jeśli masz inną zmienną on-nullable int b;, powinieneś wykonać zadania takie jak if (a.HasValue) { b = a.Value; } lub krótszy if (a != null) { b = a; }.

Reszta tego artykułu jest bardziej szczegółowa i pokazuje błędy, które często popełniają wielu programistów, które mogą prowadzić do NullReferenceException.

A Dokładniej

The runtime throwing a NullReferenceException zawsze oznacza to samo: próbujesz użyć referencji, a Referencja nie jest zainicjalizowana (lub była raz zainicjalizowana, ale jest już nie zainicjalizowana).

Oznacza to, że odniesienie to null, i nie można uzyskać dostępu do członków (takich jak metody) przez odniesienie null. Najprostszy przypadek:

string foo = null;
foo.ToUpper();

Spowoduje to wyświetlenie NullReferenceException w drugiej linii, ponieważ nie można wywołać metody instancji ToUpper() na referencji string wskazującej na null.

Debugowanie

Jak znaleźć źródło NullReferenceException? Oprócz samego wyjątku, który zostanie wyrzucony dokładnie w miejscu, w którym występuje, obowiązują ogólne zasady debugowania w Visual Studio: place strategiczne punkty przerwania i sprawdzają swoje zmienne , najeżdżając kursorem myszy na ich nazwy, otwierając (szybkie)okno obserwacyjne lub używając różnych paneli debugowania, takich jak lokalne i automatyczne.

Jeśli chcesz dowiedzieć się, gdzie jest ustawione odniesienie, kliknij jego nazwę prawym przyciskiem myszy i wybierz "Znajdź wszystkie odniesienia". Następnie możesz umieścić punkt przerwania w każdej znalezionej lokalizacji i uruchomić program z dołączonym debugerem. Za każdym razem, gdy debugger się zepsuje na takim punkcie przerwania, musisz aby określić, czy odniesienie ma być inne niż null, sprawdź zmienną i sprawdź, czy wskazuje na wystąpienie, gdy tego oczekujesz.

Śledząc przebieg programu w ten sposób, możesz znaleźć miejsce, w którym instancja nie powinna być null i dlaczego nie jest prawidłowo ustawiona.

Przykłady

Niektóre typowe scenariusze, w których można wyrzucić wyjątek:

Ogólne

ref1.ref2.ref3.member

Jeśli ref1 lub ref2 lub ref3 jest równe null, to otrzymasz NullReferenceException. Jeśli jeśli chcesz rozwiązać problem, dowiedz się, który z nich jest null, przepisując wyrażenie do prostszego odpowiednika:

var r1 = ref1;
var r2 = r1.ref2;
var r3 = r2.ref3;
r3.member

W szczególności, w HttpContext.Current.User.Identity.Name, HttpContext.Current może być null, lub User właściwość może być null, lub Identity właściwość może być null.

Pośrednie

public class Person 
{
    public int Age { get; set; }
}
public class Book 
{
    public Person Author { get; set; }
}
public class Example 
{
    public void Foo() 
    {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; // You never initialized the Author property.
                                       // there is no Person to get an Age from.
    }
}

Jeśli chcesz uniknąć dziecięcego (Person) odniesienia null, możesz zainicjować je w konstruktorze obiektu rodzica (Książki).

Inicjalizatory Zagnieżdżonego Obiektu

Ten sam zastosowanie do inicjalizatorów zagnieżdżonych obiektów:

Book b1 = new Book 
{ 
   Author = { Age = 45 } 
};

To tłumaczy się na:

Book b1 = new Book();
b1.Author.Age = 45;

Podczas gdy używane jest słowo kluczowe new, tworzy ono tylko nową instancję Book, ale nie nową instancję Person, więc Author właściwość jest nadal null.

Inicjalizatory Zagnieżdżonej Kolekcji

public class Person 
{
    public ICollection<Book> Books { get; set; }
}
public class Book 
{
    public string Title { get; set; }
}

Zagnieżdżona kolekcja Initializers zachowuje się tak samo:

Person p1 = new Person 
{
    Books = {
         new Book { Title = "Title1" },
         new Book { Title = "Title2" },
    }
};

To tłumaczy się na:

Person p1 = new Person();
p1.Books.Add(new Book { Title = "Title1" });
p1.Books.Add(new Book { Title = "Title2" });

new Person tworzy tylko instancję Person, ale zbiór Books jest nadal null. Składnia kolekcji Initializer nie tworzy kolekcji dla p1.Books, tłumaczy się tylko na p1.Books.Add(...) wypowiedzi.

Tablica

int[] numbers = null;
int n = numbers[0]; // numbers is null. There is no array to index.

Elementy Tablicy

Person[] people = new Person[5];
people[0].Age = 20 // people[0] is null. The array was allocated but not
                   // initialized. There is no Person to set the Age for.

Postrzępione Tablice

long[][] array = new long[1][];
array[0][0] = 3; // is null because only the first dimension is yet initialized.
                 // Use array[0] = new long[2]; first.

Kolekcja / Lista / Słownik

Dictionary<string, int> agesForNames = null;
int age = agesForNames["Bob"]; // agesForNames is null.
                               // There is no Dictionary to perform the lookup.

Zmienna Zakresu (Pośredni/Odroczony)

public class Person 
{
    public string Name { get; set; }
}
var people = new List<Person>();
people.Add(null);
var names = from p in people select p.Name;
string firstName = names.First(); // Exception is thrown here, but actually occurs
                                  // on the line above.  "p" is null because the
                                  // first element we added to the list is null.

Events (C#)

public class Demo
{
    public event EventHandler StateChanged;
    
    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e); // Exception is thrown here 
                               // if no event handlers have been attached
                               // to StateChanged event
    }
}

(Uwaga: VB.NET kompilator wstawia null sprawdza użycie zdarzeń, więc nie jest konieczne sprawdzanie zdarzeń dla Nothing W VB.NET.)

Złe Konwencje Nazewnictwa:

Jeśli nazwałeś pola inaczej niż lokalne, mogłeś zdać sobie sprawę, że nigdy nie zainicjowałeś tego pola.

public class Form1
{
    private Customer customer;
    
    private void Form1_Load(object sender, EventArgs e) 
    {
        Customer customer = new Customer();
        customer.Name = "John";
    }
    
    private void Button_Click(object sender, EventArgs e)
    {
        MessageBox.Show(customer.Name);
    }
}
Można to rozwiązać stosując konwencję do pól przedrostkowych z podkreśleniem:
    private Customer _customer;

ASP.NET cykl życia strony:

public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
             // Only called on first load, not when button clicked
             myIssue = new TestIssue(); 
        }
    }
        
    protected void SaveButton_Click(object sender, EventArgs e)
    {
        myIssue.Entry = "NullReferenceException here!";
    }
}

ASP.NET wartości sesji

// if the "FirstName" session value has not yet been set,
// then this line will throw a NullReferenceException
string firstName = Session["FirstName"].ToString();

ASP.NET modele MVC empty view

Jeśli wyjątek występuje, gdy odwołujemy się do właściwości {[93] } w ASP.NET MVC View, musisz zrozumieć, że Model zostanie ustawiona w Twojej metodzie akcji, gdy return zobaczysz. Po zwróceniu pustego modelu (lub właściwości modelu) z kontrolera, wyjątek występuje, gdy widoki uzyskują do niego dostęp:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
        return View();  // Forgot the provide a Model here.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
{
}
    
<p>@Model.somePropertyName</p> <!-- Also throws -->

Kolejność tworzenia kontroli WPF i zdarzenia

WPF kontrolki są tworzone podczas wywołania InitializeComponent w kolejności, w jakiej pojawiają się w drzewie wizualnym. A NullReferenceException zostanie podniesione w przypadku wcześnie utworzonych kontrolek z narzędziami obsługi zdarzeń itp. , że ogień podczas InitializeComponent, które odwołują się do późno utworzonych kontrolek.

Na przykład:

<Grid>
    <!-- Combobox declared first -->
    <ComboBox Name="comboBox1" 
              Margin="10"
              SelectedIndex="0" 
              SelectionChanged="comboBox1_SelectionChanged">
       <ComboBoxItem Content="Item 1" />
       <ComboBoxItem Content="Item 2" />
       <ComboBoxItem Content="Item 3" />
    </ComboBox>
        
    <!-- Label declared later -->
    <Label Name="label1" 
           Content="Label"
           Margin="10" />
</Grid>

Tutaj comboBox1 jest tworzony przed label1. Jeśli comboBox1_SelectionChanged spróbuje odwołać się do ' label1, nie zostanie on jeszcze utworzony.

private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!!
}

Zmiana kolejności deklaracji w XAML (tj. lista label1 przed comboBox1, ignorując kwestie filozofii projektowania, rozwiązałaby przynajmniej NullReferenceException tutaj.

Obsada z as

var myThing = someObject as Thing;

To nie rzuca InvalidCastException ale zwraca null, gdy obsada nie powiedzie się (i gdy someObject jest samo null). Więc bądźcie tego świadomi.

LINQ FirstOrDefault() i SingleOrDefault()

Proste wersje First() i Single() rzucają wyjątki, gdy nic nie ma. Wersje "OrDefault" zwracają w tym przypadku null. Więc bądźcie tego świadomi.

Foreach

foreach rzuca, gdy próbujesz iterować kolekcję null. Zwykle spowodowane nieoczekiwanym wynikiem null z metod zwracających zbiory.

List<int> list = null;    
foreach(var v in list) { } // exception

Więcej realistyczny przykład-wybierz węzły z dokumentu XML. Rzuci, jeśli węzły nie zostaną znalezione, ale początkowe debugowanie pokazuje, że wszystkie właściwości są poprawne:

foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))

Sposoby na unikanie

Jawnie sprawdza null i ignoruje wartości null.

Jeśli spodziewasz się czasami, że Referencja będzie null, możesz sprawdzić, czy jest ona null przed uzyskaniem dostępu do członków instancji:

void PrintName(Person p)
{
    if (p != null) 
    {
        Console.WriteLine(p.Name);
    }
}

Jawnie sprawdź null i podaj wartość domyślną.

Metody wywołują oczekiwanie zwrócenie instancji może zwrócić null, na przykład gdy poszukiwany obiekt nie może zostać znaleziony. W takim przypadku można zwrócić wartość domyślną:

string GetCategory(Book b) 
{
    if (b == null)
        return "Unknown";
    return b.Category;
}

Jawnie sprawdza null Z wywołań metod i rzuca Niestandardowy wyjątek.

Możesz również rzucić Niestandardowy wyjątek, tylko po to, aby go złapać w kodzie wywołującym:

string GetCategory(string bookTitle) 
{
    var book = library.FindBook(bookTitle);  // This may return null
    if (book == null)
        throw new BookNotFoundException(bookTitle);  // Your custom exception
    return book.Category;
}

Użyj Debug.Assert jeśli wartość Nigdy nie powinna być null, aby złapać problem wcześniej niż wystąpi wyjątek.

Kiedy w trakcie tworzenia należy wiedzieć, że metoda może, ale nigdy nie powinna zwracać null, można użyć Debug.Assert(), aby złamać tak szybko, jak to możliwe, gdy wystąpi:

string GetTitle(int knownBookID) 
{
    // You know this should never return null.
    var book = library.GetBook(knownBookID);  

    // Exception will occur on the next line instead of at the end of this method.
    Debug.Assert(book != null, "Library didn't return a book for known book ID.");

    // Some other code

    return book.Title; // Will never throw NullReferenceException in Debug mode.
}

Chociaż to sprawdzenie nie zakończy się w kompilacji wydania , powodując ponowne rzucenie NullReferenceException, gdy book == null jest uruchomiony w trybie wydania.

Użyj GetValueOrDefault() dla typów wartości nullable, aby podać wartość domyślną, gdy są null.

DateTime? appointment = null;
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the default value provided (DateTime.Now), because appointment is null.

appointment = new DateTime(2022, 10, 20);
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the appointment date, not the default

Użyj operatora null: ?? [C#] lub If() [VB].

W związku z tym, że nie jest to możliwe, nie jest to możliwe.]}
IService CreateService(ILogger log, Int32? frobPowerLevel)
{
   var serviceImpl = new MyService(log ?? NullLog.Instance);
 
   // Note that the above "GetValueOrDefault()" can also be rewritten to use
   // the coalesce operator:
   serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
}

Użyj operatora warunku null: ?. lub ?[x] dla tablic (dostępnych w C# 6 i VB.NET 14):

Jest to również czasami nazywane bezpieczną nawigacją lub operatorem Elvisa (po jego kształcie). Jeśli wyrażenie po lewej stronie operatora ma wartość null, wtedy prawa strona nie będzie obliczana, a zamiast tego zwracane jest null. Oznacza to przypadki takie jak:
var title = person.Title.ToUpper();

Jeśli osoba nie ma tytułu, spowoduje to wyrzucenie wyjątku, ponieważ próbuje wywołać ToUpper na właściwości o wartości null.

W C# 5 i poniżej, można to zabezpieczyć za pomocą:

var title = person.Title == null ? null : person.Title.ToUpper();

Teraz zmienna title będzie null zamiast rzucać wyjątek. C# 6 wprowadza do tego krótszą składnię:

var title = person.Title?.ToUpper();

Spowoduje to, że zmienna title będzie null, a wywołanie do ToUpper nie zostanie wykonane, jeśli person.Title będzie null.

Oczywiście, że ty nadal trzeba sprawdzić title dla null lub użyć operatora warunku null razem z operatorem koalescencyjnym null (??), aby podać domyślną wartość:

// regular null check
int titleLength = 0;
if (title != null)
    titleLength = title.Length; // If title is null, this would throw NullReferenceException
    
// combining the `?` and the `??` operator
int titleLength = title?.Length ?? 0;

Podobnie, dla tablic można użyć ?[i] w następujący sposób:

int[] myIntArray = null;
var i = 5;
int? elem = myIntArray?[i];
if (!elem.HasValue) Console.WriteLine("No value");

Zrobi to następująco: Jeśli myIntArray jest null, wyrażenie zwraca null i można je bezpiecznie sprawdzić. Jeśli zawiera tablicę, zrobi to samo, co: elem = myIntArray[i]; i zwraca element i<sup>th</sup>.

Użyj kontekstu null (dostępny w C # 8):

Wprowadzone w C# 8 tam typy referencyjne null context i nullable wykonują statyczną analizę zmiennych i dostarczają ostrzeżenia kompilatora, jeśli wartość może być potencjalnie null lub została ustawiona na null. Nullable reference types pozwala typom być jawnie dozwolone jako null.

Nullable annotation context i nullable warning context mogą być ustawione dla projektu przy użyciu elementu Nullable w pliku csproj. Ten element konfiguruje sposób kompilatora interpretuje nullability typów i jakie ostrzeżenia są generowane. Poprawne ustawienia to:

  • enable: włączony jest kontekst nullable adnotation. Włączony jest nullable warning context. Zmienne typu reference, na przykład string, nie są nullable. Wszystkie ostrzeżenia o nullability są włączone.
  • disable: kontekst nullable adnotacji jest wyłączony. Nieaktywny kontekst ostrzeżenia jest wyłączony. Zmienne typu odniesienia są nieświadome, podobnie jak wcześniejsze wersje C#. Wszystkie ostrzeżenia o nieważności są wyłączone.
  • safeonly: włączony jest kontekst nullable adnotation. Nullable warning context to safeonly. Zmienne typu odniesienia są nonnullable. Wszystkie ostrzeżenia o zerowaniu bezpieczeństwa są włączone.
  • warnings: kontekst nullable adnotacji jest wyłączony. Włączony jest nullable warning context. Zmienne typu odniesienia są nieświadome. Wszystkie ostrzeżenia o nullability są włączone.
  • safeonlywarnings: nullable annotation context to niepełnosprawni. Nullable warning context to safeonly. Zmienne typu odniesienia są nieświadome. Wszystkie ostrzeżenia o zerowaniu bezpieczeństwa są włączone.

Nullable reference type jest notowany przy użyciu tej samej składni co nullable value types: a ? jest dołączany do typu zmiennej.

Specjalne techniki debugowania i naprawiania zerowych derefów w iteratorach

C# obsługuje " bloki iteratora "(zwane w niektórych innych popularnych językach" generatorami"). Null wyjątki dereferencyjne mogą być szczególnie trudne do debugowania w blokach iteratora z powodu odroczenia wykonania:

public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    for (int i = 0; i < count; ++i)
    yield return f.MakeFrob();
}
...
FrobFactory factory = whatever;
IEnumerable<Frobs> frobs = GetFrobs();
...
foreach(Frob frob in frobs) { ... }

Jeśli whatever daje null to MakeFrob rzuci. Teraz możesz pomyśleć, że właściwą rzeczą jest to:

// DON'T DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
   if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
   for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

Dlaczego to jest złe? Ponieważ blok iteratora nie działa aż do foreach! Wywołanie GetFrobspo prostu zwraca obiekt, który po iteracji uruchomi blok iteratora.

Pisząc takie sprawdzenie null zapobiega dereferencji null, ale przenosi wyjątek argumentu null do punktu iteracji , a nie do punktu wywołania , a to jest bardzo mylące w debugowaniu.

Poprawną poprawką jest:

// DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
   // No yields in a public method that throws!
   if (f == null) 
       throw new ArgumentNullException("f", "factory must not be null");
   return GetFrobsForReal(f, count);
}
private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
{
   // Yields in a private method
   Debug.Assert(f != null);
   for (int i = 0; i < count; ++i)
        yield return f.MakeFrob();
}

Oznacza to utworzenie prywatnej metody pomocniczej, która ma logikę bloku iteratora, oraz publicznej metody powierzchniowej, która sprawdza null i zwraca iterator. Teraz, gdy GetFrobs jest wywołana, następuje sprawdzenie null natychmiast, a następnie GetFrobsForReal wykonuje po iteracji sekwencji.

Jeśli zbadasz źródło odniesienia dla LINQ obiektów zobaczysz, że ta technika jest używana przez cały czas. Jest nieco bardziej niezgrabny w pisaniu, ale znacznie ułatwia debugowanie błędów nieważności. zoptymalizuj kod dla wygody rozmówcy, a nie dla wygody autora .

Notatka o zerowych dereferencjach w kodzie niebezpiecznym

C# posiada tryb "niebezpieczny", który jest, jak sama nazwa wskazuje, niezwykle niebezpieczne, ponieważ normalne mechanizmy bezpieczeństwa, które zapewniają bezpieczeństwo pamięci i bezpieczeństwa typu, nie są egzekwowane. nie powinieneś pisać niebezpiecznego kodu, jeśli nie masz dokładnego i głębokiego zrozumienia, jak działa pamięć.

W trybie niebezpiecznym należy zdawać sobie sprawę z dwóch ważnych faktów:]}
  • dereferencja null wskaźnik tworzy ten sam wyjątek co dereferencja null odniesienie
  • dereferencja nieprawidłowego wskaźnika non-null może wytworzyć ten wyjątek w pewnych okolicznościach

Aby zrozumieć, dlaczego tak jest, pomaga zrozumieć, w jaki sposób.NET produkuje wyjątki dereferencyjne null w pierwszej kolejności. (Te dane dotyczą. NET działającego w systemie Windows; inne systemy operacyjne używają podobnych mechanizmów.)

Pamięć jest zwirtualizowana w Windows; każdy proces otrzymuje wirtualną przestrzeń pamięci wielu "stron" pamięci które są śledzone przez system operacyjny. Każda strona pamięci ma ustawione flagi, które określają sposób jej użycia: read from, written to, executed, i tak dalej. najniższa strona jest oznaczona jako "produce an error if ever used in any way".

Zarówno wskaźnik null, jak i odniesienie null w {[158] } są wewnętrznie reprezentowane jako liczba zero, więc każda próba przeniesienia jej do odpowiadającej jej pamięci powoduje, że system operacyjny generuje błąd. . NET runtime wykrywa ten błąd i zamienia go w wyjątek dereferencji null.

Dlatego dereferencja zarówno wskaźnika null, jak i odniesienia null powoduje ten sam wyjątek.

A co z drugim punktem? Dereferencja dowolny nieprawidłowy wskaźnik, który znajduje się na najniższej stronie pamięci wirtualnej, powoduje ten sam błąd systemu operacyjnego, a tym samym ten sam wyjątek. Dlaczego to ma sens? Załóżmy, że mamy strukturę zawierającą dwa inty i niezarządzany wskaźnik równy null. Jeśli spróbujemy dereferencji drugiej int w strukturze, CLR nie spróbuje uzyskać dostępu do magazynu w lokalizacji zero; uzyska dostęp do magazynu w lokalizacji czwartej. Ale logicznie jest to dereferencja null, ponieważ docieramy do tego adresu poprzez null.

Jeśli pracujesz z niebezpiecznym kodem i dostajesz wyjątek dereferencji null, pamiętaj, że wskaźnik nie musi być null. Może to być dowolne miejsce w najniższa strona, a ten wyjątek zostanie wytworzony.

 2494
Author: LopDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-19 08:56:30

Wyjątek NullReference-Visual Basic

NullReference Exception Dla Visual Basic nie różni się niczym od tego w C#. W końcu obaj zgłaszają ten sam wyjątek zdefiniowany w. NET Framework, którego obaj używają. Przyczyny unikalne dla Visual Basic są rzadkie (być może tylko jedna).

Ta odpowiedź będzie używać terminów Visual Basic, składni i kontekstu. Użyte przykłady pochodzą z dużej liczby przeszłych pytań dotyczących przepełnienia stosu. Ma to na celu zmaksymalizowanie znaczenie poprzez użycie rodzajów sytuacji często widywanych w postach. Nieco więcej wyjaśnień jest również dla tych, którzy mogą go potrzebować. Przykład podobny do twojego jest bardzo prawdopodobnie wymieniony tutaj.

Uwaga:

  1. jest to oparte na koncepcji: nie ma kodu, który można wkleić do projektu. Jego celem jest pomoc w zrozumieniu, co powoduje NullReferenceException (NRE), jak go znaleźć, jak go naprawić i jak go uniknąć. NRE może być spowodowane na wiele sposobów więc jest mało prawdopodobne, aby było to twoje jedyne spotkanie.
  2. przykłady (ze Stack Overflow posts) nie zawsze pokazują najlepszy sposób na zrobienie czegoś w pierwszej kolejności.
  3. zazwyczaj stosuje się najprostszy środek.

Podstawowe Znaczenie

Komunikat "Obiekt nie jest ustawiony na instancję obiektu" oznacza, że próbujesz użyć obiektu, który nie został zainicjowany. To sprowadza się do jednego z nich:

  • Twój kod zadeklarował zmienną obiektową, ale nie zainicjalizował it (Utwórz instancję lub 'instancję ' it)
  • coś, co twój kod zakłada, że zainicjalizuje obiekt, nie
  • [216]} możliwe, że inny kod przedwcześnie unieważnił obiekt nadal używany [217]}

Znalezienie Przyczyny

Ponieważ problemem jest odniesienie do obiektu, które jest Nothing, odpowiedzią jest zbadanie ich, aby dowiedzieć się, który z nich. Następnie określ, dlaczego jest nie zainicjowany. Przytrzymaj mysz nad różnymi zmiennymi, a Visual Studio (VS) pokaże ich wartości - winowajcą będzie Nothing.

Wyświetlanie debugowania IDE

Należy również usunąć wszelkie bloki Try/Catch z odpowiedniego kodu, zwłaszcza te, w których nie ma nic w bloku Catch. Spowoduje to awarię kodu, gdy spróbuje użyć obiektu Nothing. to jest to, czego chcesz , ponieważ określi dokładną lokalizację problemu, a pozwala zidentyfikować obiekt, który go powoduje.

A MsgBox W haczyku, który wyświetla {[57] } będzie mało pomocny. Ta metoda prowadzi również do bardzo złych pytań , ponieważ nie można opisać rzeczywistego wyjątku, obiektu lub nawet linii kodu, w której to się dzieje.

Możesz również użyć Locals Window (Debug - > Windows - > Locals ), aby zbadać obiekty.

Kiedy wiesz, co i gdzie jest problem, to zwykle dość łatwe do naprawienia i szybsze niż publikowanie nowego pytania.

Zobacz też:

Przykłady i środki zaradcze

Obiekty klasy / Tworzenie instancji

Dim reg As CashRegister
...
TextBox1.Text = reg.Amount         ' NRE

Problem polega na tym, że Dim nie tworzy obiektu CashRegister ; deklaruje tylko zmienna o nazwie reg tego typu. deklarowanie zmiennej obiektowej i tworzenie instancji to dwie różne rzeczy.

Remedy

Operator New może być często używany do utworzenia instancji, gdy ją zadeklarujesz:

Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor

' Longer, more explicit form:
Dim reg As CashRegister = New CashRegister

Gdy właściwe jest utworzenie instancji później:

Private reg As CashRegister         ' Declare
  ...
reg = New CashRegister()            ' Create instance

Uwaga: nie należy ponownie używać Dim w procedurze, w tym konstruktora (Sub New):

Private reg As CashRegister
'...

Public Sub New()
   '...
   Dim reg As New CashRegister
End Sub

To będzie tworzy zmienną local , reg, która istnieje tylko w tym kontekście (sub). Zmienna reg z poziomem modułu Scope, której będziesz używać wszędzie indziej, pozostaje Nothing.

Brak operatora New jest przyczyną #1NullReference Exceptions widziane w pytaniach przepełnienia stosu.

Visual Basic stara się wyjaśnić proces wielokrotnie za pomocą New: Korzystanie z New Operator tworzy nowy obiekt i połączenia Sub New -- konstruktor -- gdzie twój obiekt może wykonać dowolną inną inicjalizację.

Dla jasności, Dim (lub Private) tylko deklaruje zmienną i jej Type. zakres zmiennej - niezależnie od tego, czy istnieje dla całego modułu / klasy, czy jest lokalny dla procedury-jest określony przez , gdzie jest zadeklarowana. Private | Friend | Public definiuje poziom dostępu, a nie zakres .

Aby uzyskać więcej informacji, zobacz:


Tablice

Tablice muszą być również utworzone:

Private arr as String()

Ta tablica została tylko zadeklarowana, a nie utworzona. Istnieje kilka sposobów inicjalizacji tablicy:

Private arr as String() = New String(10){}
' or
Private arr() As String = New String(10){}

' For a local array (in a procedure) and using 'Option Infer':
Dim arr = New String(10) {}

Uwaga: począwszy od VS 2010, podczas inicjalizacji lokalnego tablica z literałami i Option Infer, elementy As <Type> i New są opcjonalne:

Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14}
Dim myDbl() = {1.5, 2, 9.9, 18, 3.14}

Typ danych i rozmiar tablicy są wnioskowane na podstawie przypisywanych danych. Deklaracje poziomu klasy / modułu nadal wymagają As <Type> Z Option Strict:

Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}

Przykład: tablica obiektów klasy

Dim arrFoo(5) As Foo

For i As Integer = 0 To arrFoo.Count - 1
   arrFoo(i).Bar = i * 10       ' Exception
Next

Tablica została utworzona, ale Foo obiekty w niej nie.

Remedy

For i As Integer = 0 To arrFoo.Count - 1
    arrFoo(i) = New Foo()         ' Create Foo instance
    arrFoo(i).Bar = i * 10
Next

Użycie List(Of T) sprawi, że będzie to dość trudne do element bez poprawnego obiektu:

Dim FooList As New List(Of Foo)     ' List created, but it is empty
Dim f As Foo                        ' Temporary variable for the loop

For i As Integer = 0 To 5
    f = New Foo()                    ' Foo instance created
    f.Bar =  i * 10
    FooList.Add(f)                   ' Foo object added to list
Next

Aby uzyskać więcej informacji, zobacz:


Listy i kolekcje

Zbiory. NET (których jest wiele odmian-listy, Słownik itp.) musi być również utworzony lub utworzony.

Private myList As List(Of String)
..
myList.Add("ziggy")           ' NullReference

Dostajesz ten sam wyjątek z tego samego powodu - myList została tylko zadeklarowana, ale żadna instancja nie została utworzona. Środek jest taki sam:

myList = New List(Of String)

' Or create an instance when declared:
Private myList As New List(Of String)

Wspólny Nadzór to klasa, która używa zbioru Type:

Public Class Foo
    Private barList As List(Of Bar)

    Friend Function BarCount As Integer
        Return barList.Count
    End Function

    Friend Sub AddItem(newBar As Bar)
        If barList.Contains(newBar) = False Then
            barList.Add(newBar)
        End If
    End Function

Każda procedura spowoduje NRE, ponieważ barList jest tylko zadeklarowana, a nie instancyjna. Utworzenie instancji Foo nie spowoduje również utworzenia instancji wewnętrznej barList. W przeciwieństwie do innych konstruktorów, nie jest to możliwe.]}

Public Sub New         ' Constructor
    ' Stuff to do when a new Foo is created...
    barList = New List(Of Bar)
End Sub

Jak poprzednio, jest to niepoprawne:

Public Sub New()
    ' Creates another barList local to this procedure
     Dim barList As New List(Of Bar)
End Sub

Więcej informacje, zobacz List(Of T) Klasa .


Obiekty Dostawcy Danych

Praca z bazami danych daje wiele możliwości dla NullReference, ponieważ może być wiele obiektów (Command, Connection, Transaction, Dataset, DataTable, DataRows....) w użyciu jednocześnie. Uwaga: nie ma znaczenia, którego dostawcy danych używasz -- MySQL, SQL Server, OleDB itp. -- pojęcia są takie same.

Przykład 1

Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows As Integer

con.Open()
Dim sql = "SELECT * FROM tblfoobar_List"
da = New OleDbDataAdapter(sql, con)
da.Fill(ds, "foobar")
con.Close()

MaxRows = ds.Tables("foobar").Rows.Count      ' Error

Jak poprzednio, obiekt ds Dataset został zadeklarowany, ale instancja nigdy nie została utworzona. DataAdapter wypełni istniejący DataSet, a nie utworzy. W tym przypadku, ponieważ ds jest zmienną lokalną, IDE ostrzega cię , że może się to zdarzyć:

img

Gdy jest zadeklarowana jako zmienna poziomu modułu / klasy, jak to wygląda w przypadku con, kompilator nie może wiedzieć, czy obiekt został utworzony przez procedurę upstream. Nie ignoruj Ostrzeżenia.

Remedy

Dim ds As New DataSet

Przykład 2

ds = New DataSet
da = New OleDBDataAdapter(sql, con)
da.Fill(ds, "Employees")

txtID.Text = ds.Tables("Employee").Rows(0).Item(1)
txtID.Name = ds.Tables("Employee").Rows(0).Item(2)

Literówka jest tu problemem: Employees vs Employee. Nie utworzono DataTable o nazwie "pracownik", więc NullReferenceException próbuje uzyskać do niego dostęp. Innym potencjalnym problemem jest założenie, że będzie Items, co może nie być, gdy SQL zawiera klauzulę WHERE.

Remedy

Ponieważ używa się jednej tabeli, użycie Tables(0) pozwoli uniknąć błędów ortograficznych. Badanie Rows.Count może również pomóc:

If ds.Tables(0).Rows.Count > 0 Then
    txtID.Text = ds.Tables(0).Rows(0).Item(1)
    txtID.Name = ds.Tables(0).Rows(0).Item(2)
End If

Fill jest to funkcja zwracająca liczbę Rows, która może być również przetestowana:

If da.Fill(ds, "Employees") > 0 Then...

Przykład 3

Dim da As New OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
        TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
        FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)
Dim ds As New DataSet
da.Fill(ds)

If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then

DataAdapter dostarczy TableNames, jak pokazano w poprzednim przykładzie, ale nie przetwarza nazw z tabeli SQL lub bazy danych. W rezultacie ds.Tables("TICKET_RESERVATION") odwołuje się do nieistniejącej tabeli.

The remedium jest takie samo, odwołaj się do tabeli według indeksu:

If ds.Tables(0).Rows.Count > 0 Then

Zobacz Klasa DataTable .


Ścieżki Obiektów / Zagnieżdżone

If myFoo.Bar.Items IsNot Nothing Then
   ...

Kod jest tylko testem Items podczas gdy zarówno myFoo, jak i Bar mogą być również niczym. W ten sposób możliwe jest sprawdzenie całego łańcucha lub ścieżki obiektów po kolei.]}

If (myFoo IsNot Nothing) AndAlso
    (myFoo.Bar IsNot Nothing) AndAlso
    (myFoo.Bar.Items IsNot Nothing) Then
    ....

AndAlso to ważne. Kolejne testy nie będą wykonywane po napotkaniu pierwszego warunku False. Dzięki temu kod może bezpiecznie "wiercić" w obiektach po jednym "poziomie" na raz, oceniając myFoo.Bar tylko po (i jeśli) myFoo jest określone jako ważne. Łańcuchy obiektów lub ścieżki mogą być dość długie podczas kodowania złożonych obiektów:

myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")

Nie jest możliwe odniesienie do niczego "poniżej" obiektu null. Dotyczy to również elementów sterujących:

myWebBrowser.Document.GetElementById("formfld1").InnerText = "some value"

Tutaj, myWebBrowser lub Document może być niczym lub formfld1 element może nie istnieć.


Sterowanie UI

Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar " _
     & "FROM Invoice where invoice_no = '" & _
     Me.ComboBox5.SelectedItem.ToString.Trim & "' And category = '" & _
     Me.ListBox1.SelectedItem.ToString.Trim & "' And item_name = '" & _
     Me.ComboBox2.SelectedValue.ToString.Trim & "' And expiry_date = '" & _
     Me.expiry.Text & "'", con)

Między innymi ten kod nie przewiduje, że użytkownik może nie wybrać coś w jednej lub kilku kontrolkach interfejsu użytkownika. ListBox1.SelectedItem może być Nothing, więc ListBox1.SelectedItem.ToString spowoduje NRE.

Remedy

W związku z tym, że dane są przetwarzane w celach marketingowych, nie są przetwarzane w celach marketingowych.]}
Dim expiry As DateTime         ' for text date validation
If (ComboBox5.SelectedItems.Count > 0) AndAlso
    (ListBox1.SelectedItems.Count > 0) AndAlso
    (ComboBox2.SelectedItems.Count > 0) AndAlso
    (DateTime.TryParse(expiry.Text, expiry) Then

    '... do stuff
Else
    MessageBox.Show(...error message...)
End If

Alternatywnie możesz użyć (ComboBox5.SelectedItem IsNot Nothing) AndAlso...


Visual Basic Forms

Public Class Form1

    Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _
                   Controls("TextBox2"), Controls("TextBox3"), _
                   Controls("TextBox4"), Controls("TextBox5"), _
                   Controls("TextBox6")}

    ' same thing in a different format:
    Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}

    ' Immediate NRE:
    Private somevar As String = Me.Controls("TextBox1").Text
Jest to dość powszechny sposób na uzyskanie NRE. W C#, w zależności od sposobu kodowania, IDE zgłosi, że Controls nie istnieje w bieżącym kontekście, lub " nie może reference non-static member". Tak więc, do pewnego stopnia, jest to sytuacja tylko VB. Jest to również skomplikowane, ponieważ może spowodować kaskadę awarii.

tablice i kolekcje nie mogą być zainicjowane w ten sposób. ten kod inicjalizacyjny uruchomi się przed konstruktor utworzy Form lub Controls. W rezultacie:

  • listy i zbiory będą po prostu puste
  • tablica będzie zawierać pięć elementów niczego
  • The somevar przypisanie spowoduje natychmiastowe NRE, ponieważ nic nie ma właściwości .Text

Odwołanie się później do elementów tablicy spowoduje NRE. Jeśli zrobisz to w Form_Load, ze względu na dziwny błąd, IDE może nie zgłosić wyjątek, gdy to nastąpi. Wyjątek pojawi się później , gdy kod spróbuje użyć tablicy. Ten " cichy wyjątek "jest szczegółowo opisany w tym poście . Dla naszych celów kluczem jest to, że gdy coś podczas tworzenia formularza (ZdarzenieSub New lub Form Load) wyjątki mogą pozostać niezgłoszone, kod kończy procedurę i po prostu wyświetla formularz.

Ponieważ żaden inny kod w Twoim zdarzeniu Sub New lub Form Load nie będzie działał po NRE, wiele innych rzeczy może zostać niezaliczonych.

Sub Form_Load(..._
   '...
   Dim name As String = NameBoxes(2).Text        ' NRE
   ' ...
   ' More code (which will likely not be executed)
   ' ...
End Sub

Uwaga odnosi się to do wszelkich odniesień do kontroli i komponentów, które sprawiają, że są one nielegalne, gdzie są:

Public Class Form1

    Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
    Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
    Private studentName As String = TextBox13.Text

Częściowe Remedy

Ciekawe jest to, że VB nie dostarcza ostrzeżenia, ale rozwiązaniem jest zadeklarowanie kontenerów na poziomie formularza, ale zainicjowanie w obsłudze zdarzenia ładowania formularza, gdy kontrolki istnieją. Można to zrobić w Sub New tak długo, jak Twój kod jest po wywołaniu InitializeComponent:

' Module level declaration
Private NameBoxes as TextBox()
Private studentName As String

' Form Load, Form Shown or Sub New:
'
' Using the OP's approach (illegal using OPTION STRICT)
NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...)
studentName = TextBox32.Text           ' For simple control references

Kod tablicy może jeszcze nie wyjść z lasu. Wszystkie kontrolki znajdujące się w kontrolce kontenera (jak GroupBox lub Panel) nie zostaną znalezione w Me.Controls; będą w kolekcji kontrolek tego panelu lub GroupBox. Kontrolka nie zostanie zwrócona, gdy nazwa kontrolki zostanie źle napisana ("TeStBox2"). W takich przypadkach Nothing zostanie ponownie zapisane w tych elementach tablicy, a wynik NRE zostanie wywołany, gdy spróbujesz się do niej odwołać.

Te powinny być łatwe do znalezienia teraz, gdy wiesz, czego szukasz: VS pokazuje błąd swoich sposobów

"Button2" Panel

Remedy

Zamiast pośrednich odniesień po nazwie, używając zbioru formularza Controls, użyj referencji kontrolnej:

' Declaration
Private NameBoxes As TextBox()

' Initialization -  simple and easy to read, hard to botch:
NameBoxes = New TextBox() {TextBox1, TextBox2, ...)

' Initialize a List
NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})
' or
NamesList = New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})

Funkcja Nic Nie Zwraca

Private bars As New List(Of Bars)        ' Declared and created

Public Function BarList() As List(Of Bars)
    bars.Clear
    If someCondition Then
        For n As Integer = 0 to someValue
            bars.Add(GetBar(n))
        Next n
    Else
        Exit Function
    End If

    Return bars
End Function

Jest to przypadek, w którym IDE ostrzega cię, że " nie wszystkie ścieżki zwracają wartość, a NullReferenceException mogą wynikać ". Możesz wyłączyć ostrzeżenie, zastępując Exit Function na Return Nothing, ale to nie rozwiązuje problemu. Wszystko, co spróbuje użyć return when someCondition = False spowoduje NRE:

bList = myFoo.BarList()
For Each b As Bar in bList      ' EXCEPTION
      ...

Remedy

Zastąp Exit Function w funkcji na Return bList. Zwracanie pustego List to nie to samo co zwracanie Nothing. Jeśli istnieje szansa, że zwracany obiekt może być Nothing, przetestuj go przed użyciem:

 bList = myFoo.BarList()
 If bList IsNot Nothing Then...

Źle Wdrożony Try / Catch

Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]}
Dim dr As SqlDataReader
Try
    Dim lnk As LinkButton = TryCast(sender, LinkButton)
    Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
    Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString()
    ViewState("username") = eid
    sqlQry = "select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
             Pager, mailaddress, from employees1 where username='" & eid & "'"
    If connection.State <> ConnectionState.Open Then
        connection.Open()
    End If
    command = New SqlCommand(sqlQry, connection)

    'More code fooing and barring

    dr = command.ExecuteReader()
    If dr.Read() Then
        lblFirstName.Text = Convert.ToString(dr("FirstName"))
        ...
    End If
    mpe.Show()
Catch

Finally
    command.Dispose()
    dr.Close()             ' <-- NRE
    connection.Close()
End Try

Jest to przypadek obiektu, który nie jest tworzony jako oczekiwany, ale również pokazuje przydatność licznika pustego Catch.

Istnieje dodatkowy przecinek w SQL (po 'mailaddress'), co powoduje wyjątek w .ExecuteReader. Po tym, jak Catch nic nie robi, Finally próbuje wykonać czyszczenie, ale ponieważ nie można Close obiektu null DataReader, powstaje zupełnie nowy NullReferenceException.

Pusty blok to diabelski plac zabaw. Ta operacja była zdumiona, dlaczego dostał NRE w bloku Finally. W innych sytuacjach pusty Catch może spowodować, że coś innego będzie dalej szumiało i sprawi, że będziesz spędzał czas na patrzeniu na złe rzeczy w niewłaściwym miejscu dla problemu. (Opisany powyżej "cichy wyjątek" dostarcza tej samej wartości rozrywkowej.)

Remedy

Nie używaj pustych bloków Try/Catch-pozwól, aby Kod uległ awarii, abyś mógł a) zidentyfikować przyczynę b) zidentyfikować lokalizację i c) zastosować odpowiednie rozwiązanie. Bloki Try/Catch nie mają na celu ukrywania wyjątków od osoba o wyjątkowych kwalifikacjach do ich naprawy-deweloper.


DBNull to nie to samo co nic

For Each row As DataGridViewRow In dgvPlanning.Rows
    If Not IsDBNull(row.Cells(0).Value) Then
        ...

Funkcja IsDBNull jest używana do sprawdzania, czy wartość jest równa System.DBNull: z MSDN:

System.Wartość DBNull wskazuje, że obiekt przedstawia brakujące lub nieistniejące dane. DBNull nie jest tym samym co Nothing, co wskazuje, że zmienna nie została jeszcze zainicjowany.

Remedy

If row.Cells(0) IsNot Nothing Then ...

Tak jak wcześniej, możesz przetestować za nic, a następnie za określoną wartość:

If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then

Przykład 2

Dim getFoo = (From f In dbContext.FooBars
               Where f.something = something
               Select f).FirstOrDefault

If Not IsDBNull(getFoo) Then
    If IsDBNull(getFoo.user_id) Then
        txtFirst.Text = getFoo.first_name
    Else
       ...

FirstOrDefault zwraca pierwszy element lub domyślną wartość, która jest Nothing dla typów referencyjnych i nigdy DBNull:

If getFoo IsNot Nothing Then...

Sterowanie

Dim chk As CheckBox

chk = CType(Me.Controls(chkName), CheckBox)
If chk.Checked Then
    Return chk
End If

Jeśli CheckBox z chkName nie można znaleźć (lub istnieje w GroupBox), to chk będzie niczym i będzie próbował odwołanie się do dowolnej właściwości spowoduje wyjątek.

Remedy

If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...

DataGridView

DGV ma kilka dziwactw widocznych okresowo:]}
dgvBooks.DataSource = loan.Books
dgvBooks.Columns("ISBN").Visible = True       ' NullReferenceException
dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"

Jeśli dgvBooks ma AutoGenerateColumns = True, utworzy kolumny, ale nie nada im nazwy, więc powyższy kod nie powiedzie się, gdy odwołuje się do nich po nazwie.

Remedy

Nazwij kolumny ręcznie lub odwołaj się do indeksu:

dgvBooks.Columns(0).Visible = True

Przykład 2-uważaj na NewRow

xlWorkSheet = xlWorkBook.Sheets("sheet1")

For i = 0 To myDGV.RowCount - 1
    For j = 0 To myDGV.ColumnCount - 1
        For k As Integer = 1 To myDGV.Columns.Count
            xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
            xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
        Next
    Next
Next

Gdy twoje DataGridView ma AllowUserToAddRows jako True (domyślne), Cells w pustym/nowym wierszu na dole wszystkie będą zawierać Nothing. Większość prób użycia zawartości (na przykład ToString) spowoduje NRE.

Remedy

Użyj pętli For/Each i przetestuj właściwość IsNewRow, aby określić, czy jest to ostatni wiersz. To działa niezależnie od tego, czy jest to prawda, czy nie.]}

For Each r As DataGridViewRow in myDGV.Rows
    If r.IsNewRow = False Then
         ' ok to use this row

Jeśli używasz pętli For n, zmodyfikuj liczbę wierszy lub użyj Exit For kiedy IsNewRow jest prawdą.


Mój.Settings (StringCollection)

W pewnych okolicznościach próba użycia elementu z My.Settings, który jest StringCollection, może skutkować referencją null przy pierwszym użyciu. Rozwiązanie jest takie samo, ale nie tak oczywiste. Consider:

My.Settings.FooBars.Add("ziggy")         ' foobars is a string collection

Ponieważ VB zarządza ustawieniami dla Ciebie, rozsądne jest oczekiwać, że zainicjuje kolekcję. Będzie, ale tylko wtedy, gdy wcześniej dodałeś wstępny wpis do kolekcji (w edytor ustawień). Ponieważ kolekcja jest (najwyraźniej) inicjalizowana po dodaniu elementu, pozostaje Nothing, gdy w edytorze ustawień nie ma elementów do dodania.

Remedy

Zainicjalizuj kolekcję ustawień w obsłudze zdarzenia formularza Load, jeśli / kiedy jest to potrzebne:

If My.Settings.FooBars Is Nothing Then
    My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If

Zazwyczaj kolekcja Settings będzie musiała zostać zainicjowana tylko przy pierwszym uruchomieniu aplikacji. Alternatywnym rozwiązaniem jest dodanie wartości początkowej do kolekcji w Project - > Settings | FooBars, Zapisz projekt, a następnie usuń fałszywą wartość.


Kluczowe Punkty

Pewnie zapomniałeś operatora.

Lub

Coś, co zakładałeś, że będzie działać bezbłędnie, aby zwrócić zainicjowany obiekt do Twojego kodu, nie.

Nie ignoruj ostrzeżeń kompilatora (ever) i używaj Option Strict On (zawsze).


Wyjątek MSDN NullReference

 320
Author: Plutonix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Innym scenariuszem jest umieszczenie obiektu null w typie wartości . Na przykład poniższy kod:

object o = null;
DateTime d = (DateTime)o;

Rzuci NullReferenceException na obsadę. Wydaje się to dość oczywiste w powyższej próbce, ale może się to zdarzyć w bardziej skomplikowanych scenariuszach, w których obiekt null został zwrócony z jakiegoś kodu, którego nie posiadasz, a cast jest na przykład generowany przez jakiś automatyczny system.

Jednym z przykładów jest to, że proste ASP.NET Wiązanie fragmentu z kalendarzem Kontrola:

<asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />

Tutaj SelectedDate jest w rzeczywistości właściwością - typu DateTime - typu sterowania sieciowego Calendar, a wiązanie może idealnie zwrócić coś null. Implicit ASP.NET Generator utworzy fragment kodu, który będzie odpowiednikiem powyższego kodu cast. A to podniesie NullReferenceException, który jest dość trudny do wykrycia, ponieważ leży w ASP.NET wygenerowany kod, który dobrze kompiluje...

 228
Author: Simon Mourier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:28:37

Oznacza to, że dana zmienna nie jest skierowana na nic. Mógłbym to tak wygenerować:

SqlConnection connection = null;
connection.Open();

To wyrzuci błąd, ponieważ chociaż zadeklarowałem zmienną " connection", to nie jest wskazywana na nic. Kiedy próbuję wywołać członka " Open", nie ma odniesienia do niego do rozwiązania, a to wyrzuci błąd.

Aby uniknąć tego błędu:

  1. zawsze inicjalizuj swoje obiekty, zanim spróbujesz coś z nimi zrobić.
  2. Jeśli nie jesteś pewien, czy obiekt jest null, sprawdź go za pomocą object == null.

Narzędzie JetBrains ' Resharper zidentyfikuje każde miejsce w kodzie, które ma możliwość wystąpienia błędu odniesienia null, co pozwala na sprawdzenie null. Ten błąd jest numerem jeden źródło błędów, IMHO.

 163
Author: Chris B. Behrens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 10:01:00

Oznacza to, że Twój kod używał zmiennej referencyjnej obiektu, która została ustawiona na null (tzn. nie odwoływała się do rzeczywistej instancji obiektu).

Aby zapobiec błędowi, obiekty, które mogą być null, powinny być testowane pod kątem null przed użyciem.

if (myvar != null)
{
    // Go ahead and use myvar
    myvar.property = ...
}
else
{
    // Whoops! myvar is null and cannot be used without first
    // assigning it to an instance reference
    // Attempting to use myvar here will result in NullReferenceException
}
 162
Author: Jonathan Wood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 19:17:10

[[8]} Należy pamiętać, że niezależnie od scenariusza, przyczyna jest zawsze taka sama w. NET:

Próbujesz użyć zmiennej referencyjnej, której wartość jest Nothing/null. Gdy wartość jest Nothing/null w przypadku zmiennej referencyjnej oznacza to, że w rzeczywistości nie przechowuje ona odwołania do instancji jakiegokolwiek obiektu, który istnieje na stercie.

Albo nigdy nie przypisałeś czegoś do zmiennej, nigdy nie utworzyłeś instancji o wartości przypisanej do zmiennej, albo Ustawiłeś zmienną równą Nothing/null ręcznie, lub wywołałeś funkcję, która ustawiła zmienną na Nothing/null dla Ciebie.

 98
Author: code master,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Przykład rzucania tego wyjątku to: gdy próbujesz coś sprawdzić, jest to null.

Na przykład:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

Środowisko uruchomieniowe. NET wyrzuci wyjątek Nullreferencexception, gdy spróbujesz wykonać akcję na czymś, co nie zostało utworzone, np. w powyższym kodzie.

W porównaniu z argumentem Nullexception, który jest zwykle rzucany jako środek obronny, jeśli metoda oczekuje, że to, co jest przekazywane do niej, nie jest null.

Więcej informacja jest w C# NullReferenceException i parametr Null.

 90
Author: Alex KeySmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:32:31

Aktualizacja C # 8.0, 2019: Nullable reference types

C#8.0 wprowadza nullable reference types i non-nullable reference types . Tak więc tylko nullable reference types muszą być sprawdzone, aby uniknąć Nullreferencexception .


Jeśli nie zainicjalizowałeś typu odniesienia i chcesz ustawić lub odczytać jedną z jego właściwości, rzuci on NullReferenceException .

Przykład:

Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.

Możesz po prostu tego uniknąć sprawdzając, czy zmienna nie jest null:

Person p = null;
if (p!=null)
{
    p.Name = "Harry"; // Not going to run to this point
}

Aby w pełni zrozumieć, dlaczego rzuca się wyjątek NullReferenceException, ważne jest, aby znać różnicę między typami wartości i [typy referencyjne] [3].

Tak więc, jeśli masz do czynienia z typami wartości , NullReferenceExceptions mogą wystąpić NIE . Chociaż musisz zachować czujność, gdy masz do czynienia z typami referencyjnymi !

Tylko typy referencyjne, jak sugeruje nazwa, mogą zawierać odniesienia lub punkt dosłownie do niczego (lub "null"). Natomiast typy wartości zawsze zawierają wartość.

Typy referencyjne (te muszą być sprawdzone):

  • dynamiczny
  • obiekt
  • string

Typy wartości (możesz po prostu zignorować te):

  • typy liczbowe
  • typy całkowe
  • typy zmiennoprzecinkowe
  • dziesiętne
  • bool
  • struktury zdefiniowane przez użytkownika
 90
Author: Fabian Bigler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-03 12:05:24

Innym przypadkiem, w którym NullReferenceExceptions może się zdarzyć, jest (nieprawidłowe) użycie as operator:

class Book {
    public string Name { get; set; }
}
class Car { }

Car mycar = new Car();
Book mybook = mycar as Book;   // Incompatible conversion --> mybook = null

Console.WriteLine(mybook.Name);   // NullReferenceException

Tutaj, Book i Car są niekompatybilnymi typami; a Car nie można przekształcić/obsadzić na a Book. Gdy ta Obsada zawiedzie, as zwraca null. Użycie mybook po tym powoduje NullReferenceException.

Ogólnie rzecz biorąc, należy użyć gipsu lub as, w następujący sposób:

Jeśli oczekujesz, że konwersja typu zawsze się powiedzie (np. wiesz, jaki obiekt powinien być wcześniej), następnie należy użyć gipsu:

ComicBook cb = (ComicBook)specificBook;

Jeśli nie jesteś pewien typu, ale chcesz spróbować użyć go jako określonego typu, użyj as:

ComicBook cb = specificBook as ComicBook;
if (cb != null) {
   // ...
}
 81
Author: Jonathon Reinhart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:33:28

Używasz obiektu, który zawiera odniesienie do wartości null. Czyli daje zerowy wyjątek. W przykładzie wartość łańcuchowa jest null i podczas sprawdzania jej długości wystąpił wyjątek.

Przykład:

string value = null;
if (value.Length == 0) // <-- Causes exception
{
    Console.WriteLine(value); // <-- Never reached
}

Błąd wyjątku to:

Nieobsługiwany Wyjątek:

System.NullReferenceException: odniesienie do obiektu nie jest ustawione na instancję przedmiotu. w programie.Main ()

 67
Author: user1814380,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Podczas gdy co powoduje NullReferenceExceptions i podejścia do avoid/fix takie wyjątki zostały rozwiązane w innych odpowiedziach, to czego wielu programistów jeszcze nie nauczyło się, jak samodzielnie debugować takie wyjątki podczas programowania.

W Visual Studio jest to zwykle łatwe dzięki Debuggerowi Visual Studio.


Najpierw upewnij się, że poprawny błąd zostanie wykryty-zobacz Jak mogę pozwolić łamanie systemu.NullReferenceException " w VS2010? Uwaga1

Wtedy albo zacznij od debugowania (F5) lub Dołącz [Debugger VS] do uruchomionego procesu. Okazjonalnie może się przydać użycie Debugger.Break, który poprosi o uruchomienie debuggera.

Teraz, gdy NullReferenceException zostanie rzucone (lub nieobsługiwane) debugger zostanie zatrzymany (pamiętasz regułę ustawioną powyżej?) na linii, na której wyjątek wystąpił. Czasami błąd będzie łatwy do wykrycia.

Na przykład, w poniższym wierszu jedynym kodem, który może spowodować wyjątek, jest jeśli myString obliczy wartość null. Można to zweryfikować patrząc na Watch Window lub uruchamiając wyrażenia w Immediate Window .

var x = myString.Trim();

W bardziej zaawansowanych przypadkach, takich jak poniższe, musisz użyć jednej z powyższych technik (Obserwuj lub natychmiastowe okna), aby sprawdzić wyrażenia w celu określenia, czy str1 było null lub jeśli str2 było null.

var x = str1.Trim() + str2.Trim();

Gdygdzie wyjątek to throw został zlokalizowany, Zwykle trywialne jest rozumowanie Wstecz, aby dowiedzieć się, gdzie wartość null została wprowadzona [niepoprawnie] --

Poświęć czas, aby zrozumieć przyczynę wyjątku. Sprawdź, czy nie ma wyrażeń null. Sprawdź poprzednie wyrażenia, które mogły spowodować takie wyrażenia null. Dodaj punkty przerwania i wykonaj odpowiednie kroki w programie. Użyj debugger.

1 jeśli Break Na rzutach jest zbyt agresywny i debugger zatrzymuje się na NPE w bibliotece.NET lub 3rd-party, Break na nieobsługiwanym przez Użytkownika może być użyty do ograniczenia przechwyconych WYJĄTKÓW. Dodatkowo VS2012 wprowadza tylko Mój kod , który również polecam włączyć.

Jeśli debugujesz z włączonym tylko moim kodem, zachowanie jest nieco inne. Po włączeniu tylko mojego kodu debugger ignoruje common pierwszej szansy wyjątki języka runtime (CLR), które są wyrzucane poza Mój kod i nie przechodzą przez Mój kod

 67
Author: user2864740,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:42:11

Simon Mourier podał ten przykład :

object o = null;
DateTime d = (DateTime)o;  // NullReferenceException

Gdzie unboxing konwersja (Obsada) z object (lub z jednej z klas System.ValueType lub System.Enum, lub z typu interfejsu) do typ wartości (inny niż Nullable<>) sam w sobie daje NullReferenceException.

W przeciwnym kierunku, a Boks konwersja z a Nullable<> która ma HasValue równe false do typu odniesienia, może dać null odniesienie, które później może prowadzić do NullReferenceException. Klasyczny przykład to:

DateTime? d = null;
var s = d.ToString();  // OK, no exception (no boxing), returns ""
var t = d.GetType();   // Bang! d is boxed, NullReferenceException

Czasami Boks dzieje się w inny sposób. Na przykład z tą niestandardową metodą rozszerzenia:

public static void MyExtension(this object x)
{
  x.ToString();
}

Następujący kod będzie problematyczny:

DateTime? d = null;
d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.

Te przypadki powstają ze względu na specjalne zasady, których runtime używa podczas boksowania instancji Nullable<>.

 61
Author: Jeppe Stig Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:34:19

Dodanie przypadku, gdy nazwa klasy dla encji użytej w encji frameworku jest taka sama jak nazwa klasy dla pliku znajdującego się za kodem formularza internetowego.

Załóżmy, że masz kontakt z formularzem internetowym.aspx, którego klasą kodową jest Contact i masz nazwę encji Contact.

Następnie następujący kod spowoduje wywołanie wyjątku NullReferenceException podczas wywoływania context.SaveChanges ()

Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Ze względu na kompletność klasy DataContext

public class DataContext : DbContext 
{
    public DbSet<Contact> Contacts {get; set;}
}

I Contact entity class. Czasami klasy encji są częściowe klasy, dzięki czemu można je rozszerzyć również w innych plikach.

public partial class Contact 
{
    public string Name {get; set;}
}

Błąd występuje, gdy encja i klasa codebehind są w tej samej przestrzeni nazw. Aby to naprawić, Zmień nazwę klasy encji lub klasy codebehind dla Contact.aspx.

Reason Nadal nie jestem pewien powodu. Ale gdy którakolwiek z klas encji rozszerzy System.Www.UI.Strona ten błąd występuje.

Do dyskusji zajrzyj na NullReferenceException w DbContext.saveChanges()

 44
Author: AbhinavRanjan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Inny ogólny przypadek, w którym można otrzymać ten wyjątek, dotyczy wyśmiewania klas podczas testów jednostkowych. Niezależnie od używanej struktury szyderczej, musisz upewnić się, że wszystkie odpowiednie poziomy hierarchii klas są odpowiednio wyśmiewane. W szczególności wszystkie właściwości HttpContext, do których odwołuje się testowany kod, muszą być wyśmiewane.

Zobacz " NullReferenceException rzucone podczas testowania Custom AuthorizationAttribute" dla nieco obszernego przykładu.

 43
Author: John Saunders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Mam inne spojrzenie na odpowiedź na to pytanie. Tego typu odpowiedzi "co jeszcze mogę zrobić, aby tego uniknąć?"

Podczas pracy na różnych warstwach, na przykład w aplikacji MVC, kontroler potrzebuje usług do wywoływania operacji biznesowych. W takich scenariuszach kontener iniekcji zależności może być użyty do inicjalizacji usług w celu uniknięcia Nullreferencexception. Oznacza to, że nie musisz się martwić o sprawdzanie null i po prostu zadzwoń do usługi od kontrolera tak, jakby zawsze były dostępne (i inicjowane) jako singleton lub prototyp.

public class MyController
{
    private ServiceA serviceA;
    private ServiceB serviceB;

    public MyController(ServiceA serviceA, ServiceB serviceB)
    {
        this.serviceA = serviceA;
        this.serviceB = serviceB;
    }

    public void MyMethod()
    {
        // We don't need to check null because the dependency injection container 
        // injects it, provided you took care of bootstrapping it.
        var someObject = serviceA.DoThis();
    }
}
 42
Author: Mukus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-29 08:44:58

W sprawie "co mam z tym zrobić" , odpowiedzi może być wiele.

Bardziej "formalnym" sposobem zapobiegania takim warunkom błędu podczas rozwijania {[12] } jest zastosowanie design by contract w Twoim kodzie. Oznacza to, że musisz ustawić w swoim systemie niezmienniki klasy , a nawet warunki wstępne i warunki postconditions .

W skrócie, niezmienniki klasy zapewniają, że tam będą pewne ograniczenia w klasie, które nie zostaną naruszone w normalnym użytkowaniu (i dlatego Klasa nie będzie w stanie niespójnym). warunki wstępne oznaczają, że dane podane jako dane wejściowe do funkcji / metody muszą być zgodne z ustawionymi ograniczeniami i nigdy nie naruszają ich, a warunki postconditions oznaczają, że wyjście funkcji/metody musi być zgodne z ustawionymi ograniczeniami ponownie bez naruszania ich. Warunki Umowy nie powinny nigdy być naruszane podczas wykonanie programu wolnego od błędów, dlatego projekt według umowy jest sprawdzany w praktyce w trybie debugowania, podczas gdy w wydaniach jest wyłączony, aby zmaksymalizować wydajność opracowanego systemu.

W ten sposób można uniknąć NullReferenceException przypadków, które są wynikiem naruszenia ustalonych ograniczeń. Na przykład, jeśli użyjesz właściwości obiektu X w klasie, a później spróbujesz wywołać jedną z jej metod i X ma wartość null, to doprowadzi to do NullReferenceException:

public X { get; set; }

public void InvokeX()
{
    X.DoSomething(); // if X value is null, you will get a NullReferenceException
}

Ale jeśli ustawisz " właściwość X nie może mieć wartości null " jako warunek wstępny metody, wtedy można zapobiec opisanemu wcześniej scenariuszowi:

//Using code contracts:
[ContractInvariantMethod]
protected void ObjectInvariant() 
{
    Contract.Invariant(X != null);
    //...
}

W tej sprawie, umowy kodowe projekt istnieje dla aplikacji. NET.

Alternatywnie projekt według umowy może być zastosowany przy użyciu twierdzenia.

UPDATE: warto wspomnieć, że termin ten został ukuty przez Bertranda Meyera w związku z jego projektem języka programowania Eiffel.

 40
Author: Nick L.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-20 00:48:38

A NullReferenceException jest wyrzucane, gdy próbujemy uzyskać dostęp do Właściwości obiektu null lub gdy wartość łańcuchowa staje się pusta i próbujemy uzyskać dostęp do metod łańcuchowych.

Na przykład:

  1. Gdy dostępna jest metoda łańcuchowa pustego łańcucha:

    string str = string.Empty;
    str.ToLower(); // throw null reference exception
    
  2. Gdy dostępna jest właściwość obiektu null:

    Public Class Person {
        public string Name { get; set; }
    }
    Person objPerson;
    objPerson.Name  /// throw Null refernce Exception 
    
 38
Author: Hemant Bavle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 06:04:10

TL; DR: Spróbuj użyć Html.Partial zamiast Renderpage


Otrzymywałem Object reference not set to an instance of an object kiedy próbowałem renderować widok w widoku, wysyłając mu Model, jak to:

@{
    MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null

Debugowanie wykazało, że model był Null wewnątrz MyOtherView. Dopóki nie zmieniłem na:

@{
    MyEntity M = new MyEntity();
}
@Html.Partial("_MyOtherView.cshtml", M);
I zadziałało.

Co więcej, powodem, dla którego nie miałem Html.Partial na początek, było to, że Visual Studio czasami rzuca błędne linie pod Html.Partial, jeśli jest wewnątrz inaczej skonstruowana pętla foreach, mimo że nie jest to tak naprawdę błąd:

@inherits System.Web.Mvc.WebViewPage
@{
    ViewBag.Title = "Entity Index";
    List<MyEntity> MyEntities = new List<MyEntity>();
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
}
<div>
    @{
        foreach(var M in MyEntities)
        {
            // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
            @Html.Partial("MyOtherView.cshtml");
        }
    }
</div>

Ale udało mi się uruchomić aplikację bez problemów z tym "błędem". Udało mi się pozbyć błędu, zmieniając strukturę pętli foreach, aby wyglądała tak:

@foreach(var M in MyEntities){
    ...
}

Chociaż mam wrażenie, że to dlatego, że Visual Studio źle odczytało ampery i nawiasy.

 33
Author: Travis Heeter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 08:35:52

Co możesz z tym zrobić?

Jest tu wiele dobrych odpowiedzi wyjaśniających, czym jest odniesienie null i jak je debugować. Ale jest bardzo niewiele na temat tego, jak zapobiec problemowi lub przynajmniej ułatwić go złapać.

Sprawdź argumenty

Na przykład, metody mogą sprawdzać różne argumenty, aby sprawdzić, czy są null i rzucać ArgumentNullException, wyjątek oczywiście stworzony w tym właśnie celu.

Konstruktor dla ArgumentNullException bierze nawet nazwę parametru i wiadomość jako argumenty, dzięki czemu można powiedzieć deweloperowi dokładnie, na czym polega problem.

public void DoSomething(MyObject obj) {
    if(obj == null) 
    {
        throw new ArgumentNullException("obj", "Need a reference to obj.");
    }
}

Użyj Narzędzi

Istnieje również kilka bibliotek, które mogą pomóc. Na przykład "Resharper" może dostarczyć ostrzeżeń podczas pisania kodu, szczególnie jeśli używasz ich atrybutu: NotNullAttribute

Jest "Microsoft Code Contracts", gdzie używasz składni jak Contract.Requires(obj != null), która daje runtime i kompilacji sprawdzanie: wprowadzanie umów kodowych .

Istnieje również "PostSharp", który pozwoli Ci po prostu używać atrybutów takich jak:

public void DoSometing([NotNull] obj)

Robiąc to i czyniąc PostSharp częścią procesu budowania obj będzie sprawdzane pod kątem null w czasie wykonywania. Zobacz: PostSharp null check

Plain Code Solution

Lub zawsze możesz zakodować własne podejście używając zwykłego starego kodu. Na przykład tutaj znajduje się struktura, której możesz użyć do przechwycenia null referencje. Jest wzorowany na tej samej koncepcji co Nullable<T>:

[System.Diagnostics.DebuggerNonUserCode]
public struct NotNull<T> where T: class
{
    private T _value;

    public T Value
    {
        get
        {
            if (_value == null)
            {
                throw new Exception("null value not allowed");
            }

            return _value;
        }
        set
        {
            if (value == null)
            {
                throw new Exception("null value not allowed.");
            }

            _value = value;
        }
    }

    public static implicit operator T(NotNull<T> notNullValue)
    {
        return notNullValue.Value;
    }

    public static implicit operator NotNull<T>(T value)
    {
        return new NotNull<T> { Value = value };
    }
}

Użyłbyś bardzo podobnie do tego samego sposobu, w jaki użyłbyś Nullable<T>, z wyjątkiem tego, aby osiągnąć dokładnie coś przeciwnego - nie dopuścić null. Oto kilka przykładów:

NotNull<Person> person = null; // throws exception
NotNull<Person> person = new Person(); // OK
NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null

NotNull<T> jest niejawnie rzucany do i z T, więc możesz go używać wszędzie, gdzie go potrzebujesz. Na przykład, możesz przekazać obiekt Person do metody, która pobiera NotNull<Person>:

Person person = new Person { Name = "John" };
WriteName(person);

public static void WriteName(NotNull<Person> person)
{
    Console.WriteLine(person.Value.Name);
}

Jak widać powyżej jak z nullable można uzyskać dostęp do wartości bazowej poprzez właściwość Value. Alternatywnie, możesz użyć jawnego lub niejawnego odlewu, możesz zobaczyć przykład z wartością zwracaną poniżej:

Person person = GetPerson();

public static NotNull<Person> GetPerson()
{
    return new Person { Name = "John" };
}

Lub możesz go nawet użyć, gdy metoda zwróci T (w tym przypadku Person), wykonując rzut. Na przykład następujący kod będzie tak samo jak powyższy kod:

Person person = (NotNull<Person>)GetPerson();

public static Person GetPerson()
{
    return new Person { Name = "John" };
}

Połącz z rozszerzeniem

Połącz NotNull<T> z metodą rozszerzenia, a możesz pokryć jeszcze więcej sytuacje. Oto przykład jak może wyglądać metoda rozszerzenia:

[System.Diagnostics.DebuggerNonUserCode]
public static class NotNullExtension
{
    public static T NotNull<T>(this T @this) where T: class
    {
        if (@this == null)
        {
            throw new Exception("null value not allowed");
        }

        return @this;
    }
}

A oto przykład, jak można go użyć:

var person = GetPerson().NotNull();

GitHub

W celach informacyjnych udostępniłem powyższy kod na Githubie, można go znaleźć pod adresem:

Https://github.com/luisperezphd/NotNull

Funkcja Języka Pokrewnego

C # 6.0 wprowadził "operator warunkowy null", który trochę w tym pomaga. Dzięki tej funkcji możesz może odwoływać się do zagnieżdżonych obiektów i jeśli któryś z nich jest null, całe wyrażenie zwraca null.

To zmniejsza liczbę kontroli null, które musisz wykonać w niektórych przypadkach. Składnia polega na umieszczeniu znaku zapytania przed każdą kropką. Weźmy na przykład następujący kod:

var address = country?.State?.County?.City;

Wyobraź sobie, że country jest obiektem typu Country, który ma właściwość o nazwie State i tak dalej. Jeśli country, State, County, or City is null then address will be null . Therefore you only have to check whether address is null`.

It ' s a great funkcja, ale daje mniej informacji. To nie oznacza, że jest oczywiste, który z 4 jest null.

Wbudowany jak Nullable?

C # ma ładny Skrót Nullable<T> , możesz zrobić coś nullable, umieszczając znak zapytania po typie tak int?.

Byłoby miło, gdyby C# miało coś w rodzaju struktury NotNull<T> powyżej i miało podobny skrót, może wykrzyknik (!) żebyś mógł napisać coś w stylu: public void WriteName(Person! person).

 23
Author: Luis Perez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-29 09:06:44

Można naprawić NullReferenceException w czysty sposób za pomocą operatorów warunkowych null W c # 6 i napisać mniej kodu do obsługi sprawdzeń null.

Jest używany do testowania null przed wykonaniem dostępu członka (?.) lub indeks (?[] operacja.

Przykład

  var name = p?.Spouse?.FirstName;

Jest równoważne:

    if (p != null)
    {
        if (p.Spouse != null)
        {
            name = p.Spouse.FirstName;
        }
    }

Wynik jest taki, że nazwa będzie null, gdy p jest null lub gdy P. małżonek jest null.

W Przeciwnym Razie do nazwy zmiennej zostanie przypisana wartość P.Imię.

Więcej Szczegółów : operatory warunkowe Null

 11
Author: M.Hassan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 23:19:36

Co ciekawe, żadna z odpowiedzi na tej stronie nie wspomina o dwóch przypadkach krawędzi, mam nadzieję, że nikt nie będzie miał nic przeciwko, jeśli je dodam: {]}

Edge case #1: współbieżny dostęp do słownika

Słowniki generyczne w. Net nie są bezpieczne dla wątków i czasami mogą rzucać NullReference lub nawet (częściej) KeyNotFoundException, gdy próbujesz uzyskać dostęp do klucza z dwóch równoległych wątków. Wyjątek jest dość mylący w tym przypadku.

Edge case # 2: unsafe code

Jeśli NullReferenceException jest wyrzucane przez unsafe Kod, możesz spojrzeć na swoje zmienne wskaźnikowe i sprawdzić je pod kątem IntPtr.Zero lub czegoś takiego. Co jest tym samym ("wyjątek wskaźnika null"), ale w kodzie niebezpiecznym zmienne są często rzutowane na typy wartości/tablice itp. i uderzasz głową o ścianę, zastanawiając się, jak typ wartości może rzucić ten wyjątek.

(kolejny powód, dla którego nie używasz niebezpiecznego kodu, chyba że go potrzebujesz, przy okazji)

Edge case # 3: Konfiguracja Multi monitora Visual Studio z drugorzędnymi monitorami, które mają różne DPI ustawienie niż Monitor główny

Ta obudowa edge jest specyficzna dla oprogramowania i odnosi się do Visual Studio 2019 IDE (i ewentualnie wcześniejszych wersji).

Metoda odtworzenia problemu: przeciągnij dowolny komponent z przybornika do formularza Windows na monitorze innym niż podstawowy z innym ustawieniem DPI niż monitor podstawowy, a otrzymasz wyskakujące okienko z "Object reference not set to an instance of an object."Zgodnie z ten wątek ten jest znany od dłuższego czasu i na czas jej napisania nie został jeszcze ustalony.

 10
Author: jazzcat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-07 17:02:41

Linia błędu " odniesienie do obiektu nie jest ustawione na instancję obiektu. "stwierdza, że nie przypisano obiektu instancji do odniesienia do obiektu i nadal uzyskujesz dostęp do właściwości/metod tego obiektu.

Na przykład: powiedzmy, że masz klasę o nazwie myClass i zawiera ona jedną właściwość prop1.

public Class myClass
{
   public int prop1 {get;set;}
}

Teraz uzyskujesz dostęp do tego prop1 w innej klasie, tak jak poniżej:

public class Demo
{
     public void testMethod()
     {
        myClass ref = null;
        ref.prop1 = 1;  //This line throws error
     }
}

Powyższa linia wyrzuca błąd, ponieważ Referencja klasy myClass jest zadeklarowana, ale nie powstała instancja lub instancja obiektu nie jest przypisana do referecne tej klasy.

Aby to naprawić, musisz utworzyć instancję (przypisać obiekt do referencji tej klasy).

public class Demo
{
     public void testMethod()
     {
        myClass ref = null;
        ref = new myClass();
        ref.prop1 = 1;  
     }
}
 9
Author: Jaimin Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 10:58:18

NullReferenceException lub odniesienie do obiektu nie ustawione na instancję obiektu występuje, gdy obiekt klasy, której próbujesz użyć, nie jest utworzony. Na przykład:

Załóżmy, że masz klasę o imieniu Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}
Zastanów się teraz nad inną klasą, w której próbujesz odzyskać pełne imię ucznia.
public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Jak widać w powyższym kodzie, stwierdzenie Student s - deklaruje tylko zmienną typu Student, zauważ, że Klasa studenta nie jest w tym momencie powstała instancja. Stąd, gdy polecenie S.GetFullName() zostanie wykonane, spowoduje to wyrzucenie wyjątku NullReferenceException.

 5
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 10:52:34

W prostych słowach:

Próbujesz uzyskać dostęp do obiektu, który nie został utworzony lub obecnie nie znajduje się w pamięci.

Więc jak sobie z tym poradzić:

  1. Debuguj i pozwól debugerowi się złamać... Przeniesie Cię bezpośrednio do zmiennej, która jest uszkodzona... Teraz twoim zadaniem jest po prostu to naprawić.. Użycie słowa kluczowego new w odpowiednim miejscu.

  2. Jeśli jest to spowodowane przez niektóre bazy danych polecenia, ponieważ obiekt nie jest obecny, to wszystkie trzeba zrobić to zrobić null check i obsłużyć:

    if (i == null) {
        // Handle this
    }
    
  3. Najtrudniejszy .. jeśli GC już go zebrałem... Zazwyczaj dzieje się tak, gdy próbujesz znaleźć obiekt za pomocą łańcuchów... Oznacza to, że znalezienie go po nazwie obiektu może się zdarzyć, że GC może już go wyczyścić... Jest to trudne do znalezienia i stanie się sporym problemem... Lepszym sposobem rozwiązania tego problemu jest przeprowadzanie kontroli zerowych tam, gdzie jest to konieczne podczas procesu rozwoju. To zaoszczędzisz dużo czasu.

Znajdując po nazwie mam na myśli jakiś framework pozwala na FIndObjects używając ciągów znaków i kod może wyglądać tak: FindObject ("ObjectName");

 4
Author: Akash Chowdary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 08:34:08

Dosłownie najprostszy sposób na poprawienie Zerowegosprawdzenie ma dwa sposoby. Jeśli masz GameObject na przykład z dołączonym skryptem i zmienną o nazwie RB (rigidbody), ta zmienna uruchomi się null podczas uruchamiania gry.
To dlatego otrzymujesz wyjątek NullReferenceException, ponieważ komputer nie ma danych przechowywanych w tej zmiennej.

Użyję zmiennej RigidBody jako przykładu.
Możemy dodawać dane naprawdę łatwo na kilka sposobów:

  1. Dodaj RigidBody do obiektu za pomocą AddComponent > Physics > Rigidbody
    Następnie wejdź do skryptu i wpisz rb = GetComponent<Rigidbody>();
    Ta linia kodu działa najlepiej pod twoimi funkcjami Start() lub Awake().
  2. możesz dodać komponent programowo i przypisać zmienną jednocześnie jedną linijką kodu: rb = AddComponent<RigidBody>();

Dalsze uwagi: jeśli chcesz, aby unity dodało komponent do Twojego obiektu, a być może zapomniałeś go dodać, możesz wpisać [RequireComponent(typeof(RigidBody))] powyżej deklaracji klasy (spacja poniżej wszystkie Twoje zastosowania).
Ciesz się i baw się tworząc gry!

 1
Author: CausticLasagne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-14 20:45:02

Jeśli weźmiemy pod uwagę typowe scenariusze, w których można rzucić ten wyjątek, uzyskamy dostęp do Właściwości z obiektem na górze.

Ex:

string postalcode=Customer.Address.PostalCode; 
//if customer or address is null , this will through exeption

Tutaj, jeśli adres jest null, wtedy otrzymasz NullReferenceException.

Tak więc, jako praktyka powinniśmy zawsze używać null check, przed uzyskaniem dostępu do właściwości w takich obiektach (szczególnie w generycznych)

string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception
 -2
Author: Hiran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 05:55:22

Jeśli ktoś otrzymuje ten Komunikat podczas zapisywania lub kompilowania kompilacji, po prostu zamknij wszystkie pliki, a następnie otwórz dowolny plik do skompilowania i zapisania.

Dla mnie powodem było to, że zmieniłem nazwę pliku i stary plik był nadal otwarty.

 -5
Author: Harshal Doshi Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 18:48:08

Jest to w zasadzie null reference exception . Jak stwierdza Microsoft-

Wyjątek NullReferenceException jest wyrzucany, gdy próbujesz uzyskać dostęp do członek typu, którego wartością jest null.

Co to znaczy?

Oznacza to, że jeśli jakiś członek, który nie posiada żadnej wartości i zmuszamy go do wykonania określonego zadania, system bez wątpienia rzuci wiadomość i powie-

"Hej czekaj, ten członek nie ma wartości więc nie może wykonać zadania, które mu przekazujesz."

Sam wyjątek mówi, że coś jest referowane, ale którego wartość nie jest ustawiana. Oznacza to, że występuje tylko podczas używania typów referencyjnych, ponieważ typy wartości nie są nullable.

NullReferenceException nie wystąpi, jeśli używamy elementów typu value.

class Program
{
    static void Main(string[] args)
    {
        string str = null;
        Console.WriteLine(str.Length);
        Console.ReadLine();
    }
}

Powyższy kod pokazuje prosty łańcuch, który jest przypisany z null wartość.

Teraz, Kiedy próbuję Wydrukować Długość z ciągu str , otrzymuję nieobsługiwany wyjątek typu 'System.NullReferenceException ' wystąpił komunikat, ponieważ member str wskazuje na null i nie może być żadnej długości null.

'Nullreferencexception' występuje również wtedy, gdy zapominamy utworzyć instancję typu referencyjnego.

Załóżmy, że mam w nim metodę klasy i członka. Nie stworzyłem swojej klasy, ale nazwałem ją swoją klasą. Teraz jeśli spróbuję użyć tej metody, kompilator wyrzuci błąd lub wyda ostrzeżenie(w zależności od kompilatora).

class Program
{
    static void Main(string[] args)
    {
        MyClass1 obj;
        obj.foo();  //Use of unassigned local variable 'obj'
    }
}

public class MyClass1
{
    internal void foo()
    {
        Console.WriteLine("hello from foo");

    }
}

Kompilator powyższego kodu powoduje błąd, że zmienna obj jest nieprzypisana, co oznacza, że nasza zmienna ma wartości null lub nic. Kompilator powyższego kodu powoduje błąd, że zmienna obj jest nieprzypisana, co oznacza, że nasza zmienna ma wartości null lub nic.

Dlaczego tak się dzieje?

  • NullReferenceException powstaje z naszej winy za nie sprawdzanie wartość obiektu. Często pozostawiamy wartości obiektów niezaznaczone w procesie tworzenia kodu.

  • Powstaje również wtedy, gdy zapominamy stworzyć instancję naszych przedmiotów. Za pomocą metod, właściwości, zbiorów itp. który może zwracać lub ustawiać wartości null może być również przyczyną tego wyjątku.

Jak można tego uniknąć?

Istnieją różne sposoby i metody, aby uniknąć tego słynnego wyjątku:

  1. Wyraźne sprawdzanie: powinniśmy stosować się do tradycji sprawdzanie obiektów, właściwości, metod, tablic i kolekcji, czy są null. Można to po prostu zaimplementować przy użyciu instrukcji warunkowych, takich jak if-else if-else itd.

  2. Obsługa wyjątków: jeden z ważnych sposobów zarządzania tym wyjątkiem. Używając prostych bloków try-catch-finally możemy kontrolować ten wyjątek, a także prowadzić jego dziennik. Może to być bardzo przydatne, gdy aplikacja jest na etapie produkcji.

  3. Operatory Null: Null operatory warunkowe typu operator i null mogą być również przydatne przy ustawianiu wartości do obiektów, zmiennych, właściwości i pól.

  4. Debugger: dla programistów, mamy wielką broń debugowania z nami. Jeśli mamy do czynienia z NullReferenceException podczas face rozwoju możemy użyć debuggera, aby dostać się do źródła wyjątku.

  5. Metoda Wbudowana: metody systemowe,takie jak GetValueOrDefault (), IsNullOrWhiteSpace() i IsNullorEmpty () sprawdzają wartość null i przypisać wartość domyślną, jeśli istnieje wartość null.

Istnieje wiele dobrych odpowiedzi już tutaj. Możesz również sprawdzić bardziej szczegółowy opis z przykładami na moim blogu .

Mam nadzieję, że to też pomoże!
 -5
Author: Wasim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 07:31:02