When I execute some code, a NullReferenceException with the following message:

Object reference not set.

or

Object reference not set to an instance of an object.

What does this mean, and how do I fix the code?

  • Added an important canonical answer from English SO What is a NullReferenceException and how do I fix it? . Now you can close most of the questions about NRE as a double, and not poke around with each individual case. All the same, almost always the same thing. - Athari
  • 3
    Need more about ?. to add. It seems not visible in the answer. - Qwertiy
  • 2
    @Qwertiy When C # 6 is relaxed - add. - Athari
  • 2
    @Discord: It's time! C # 6 is out. - VladD
  • association: stackoverflow.com/questions/4660142 - Nofate

2 answers 2

Cause

In short

You are trying to use something that is null (or Nothing in VB.NET). This means that either you assigned this value or you assigned nothing.

Like any other value, null can be passed from object to object, from method to method. If something is null in method "A", it may well be that method "B" passed this value to method "A".

The rest of the article describes what's happening in detail and lists common errors that could lead to a NullReferenceException .

In details

If the runtime throws a NullReferenceException exception, it always means one thing: you are trying to use the link. And this link is not initialized (or was initialized, but not already initialized).

This means that the link is null , and you cannot call methods through a link that is null . In the simplest case:

 string foo = null; foo.ToUpper(); 

This code will throw a NullReferenceException exception on the second line, because you cannot call the ToUpper() method of the ToUpper() reference to the string .

Debugging

How to determine the source of the error? In addition to studying the exception itself, which will be thrown exactly where it occurred, you can use general debugging guidelines in Visual Studio: put breakpoints at key points, study the values ​​of variables either by placing the mouse cursor over the variable, or by opening the debug panels: Watch, Locals, Autos.

If you want to determine the place where the link value is set or not set, right-click on its name and select "Find All References". Then you can set breakpoints on each line found and start the application in debug mode. Every time the debugging stops at a breakpoint, you can make sure that the value is correct.

Following the progress of the program, you will come to a place where the value of the link should not be null , and determine why the correct value is not assigned.

Examples

Some common examples in which an exception occurs.

Chain

 ref1.ref2.ref3.member 

If ref1 , ref2 or ref3 is null , you will get a NullReferenceException . To solve the problem and determine what exactly is null , you can rewrite the expression in a simpler way:

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

For example, in the HttpContext.Current.User.Identity.Name chain, the value may be missing for HttpContext.Current , User , and Identity .

Implicitly

 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; // Свойство Author не было инициализировано // нет Person, у которого можно вычислить Age. } } 

The same is true for nested initializers:

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

Despite the use of the new keyword, only an instance of the Book class is created, but the Person instance is not created, so the Author property remains null .

Array

 int[] numbers = null; int n = numbers[0]; // numbers = null. Нет массива, чтобы получить элемент по индексу 

Array elements

 Person[] people = new Person[5]; people[0].Age = 20; // people[0] = null. Массив создаётся, но не // инициализируется. Нет Person, у которого можно задать Age. 

Array of arrays

 long[][] array = new long[1][]; array[0][0] = 3; // = null, потому что инициализировано только первое измерение. // Сначала выполните array[0] = new long[2]. 

Collection / List / Dictionary

 Dictionary<string, int> agesForNames = null; int age = agesForNames["Bob"]; // agesForNames = null. // Экземпляр словаря не создан. 

LINQ

 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(); // Исключение бросается здесь, хотя создаётся // строкой выше. p = null, потому что // первый добавленный элемент = null. 

Developments

 public class Demo { public event EventHandler StateChanged; protected virtual void OnStateChanged(EventArgs e) { StateChanged(this, e); // Здесь бросится исключение, если на // событие StateChanged никто не подписался } } 

Unsuccessful variable naming

If the local variables and fields had different names in the code below, you would find that the field was not initialized:

 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); } } 

You can avoid problems by using the prefix for the fields:

 private Customer _customer; 

ASP.NET page life cycle

 public partial class Issues_Edit : System.Web.UI.Page { protected TestIssue myIssue; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Выполняется только на первой загрузке, но не когда нажата кнопка myIssue = new TestIssue(); } } protected void SaveButton_Click(object sender, EventArgs e) { myIssue.Entry = "NullReferenceException здесь!"; } } 

ASP.NET Sessions

 // Если сессионная переменная "FirstName" ещё не была задана, // то эта строка бросит NullReferenceException. string firstName = Session["FirstName"].ToString(); 

Empty view models of ASP.NET MVC

If you return an empty model (or model property) in the controller, I twist an exception when trying to access it:

 // Controller public class Restaurant:Controller { public ActionResult Search() { return View(); // Модель не задана. } } // Razor view @foreach (var restaurantSearch in Model.RestaurantSearch) // Исключение. { } 

Ways to avoid

Explicitly check for null , skip code

If you expect the link to be null in some cases, you can explicitly check this value before accessing the members of the instance:

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

Explicitly check for null , use default

Methods can return null , for example, if the required instance is not found. In this case, you can return the default value:

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

Explicitly check for null , throw your exception

You can also throw your exception to catch it later:

 string GetCategory(string bookTitle) { var book = library.FindBook(bookTitle); // Может вернуть null if (book == null) throw new BookNotFoundException(bookTitle); // Ваше исключение return book.Category; } 

Use Debug.Assert to check for null to detect errors before throwing an exception

If during development you know that a method can, but generally should not return null , you can use Debug.Assert to quickly find errors:

 string GetTitle(int knownBookID) { // Вы знаете, что метод не должен возвращать null var book = library.GetBook(knownBookID); // Исключение будет выброшено сейчас, а не в конце метода. Debug.Assert(book != null, "Library didn't return a book for known book ID."); // Остальной код... return book.Title; // Не выбросит NullReferenceException в режиме отладки. } 

However, this check will not work in the release build, and you will again get a NullReferenceException if book == null .

Use GetValueOrDefault() for Nullable Types

 DateTime? appointment = null; Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Отобразит значение по умолчанию, потому что appointment = null. appointment = new DateTime(2022, 10, 20); Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Отобразит дату, а не значение по умолчанию. 

Use operator ?? (C #) or If() (VB)

A brief entry to set the default values:

 IService CreateService(ILogger log, Int32? frobPowerLevel) { var serviceImpl = new MyService(log ?? NullLog.Instance); serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5; } 

Use operators ?. and ?[ (C # 6+, VB.NET 14+):

This is the operator of secure access to members, also known as the operator of Elvis for a specific form. If the expression to the left of the operator is null , then the right side is ignored, and the result is considered null . For example:

 var title = person.Title.ToUpper(); 

If the Title property is null , an exception will be thrown, because this is an attempt to call the ToUpper method on a null value. In C # 5 and below, you can add a check:

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

Now, instead of throwing an exception, the title variable will be set to null . A shorter syntax has been added to C # 6:

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

Of course, if the person variable can be null , then you need to check it too. You can also use the operators ?. and ?? together to provide a default value:

 // обычная проверка на null int titleLength = 0; if (title != null) titleLength = title.Length; // совмещаем операторы `?.` и `??` int titleLength = title?.Length ?? 0; 

If any member in the chain can be null , then you can fully protect yourself (although, of course, the architecture should be questioned):

 int firstCustomerOrderCount = customers?[0]?.Orders?.Count() ?? 0; 
  • 3
    It seems to me that the following is missing in the prevention guidelines: in most cases, the semantics of fields are non-nullable. In such cases, NRE means an error in the program logic: something is under-initialized, the object is in the wrong state. In this case, do not check for null and ignore the error (which hides a bug, but does not contribute to correcting it), but correct the code, which should guarantee that there will be no null . - VladD
  • @VladD There are too many cases where null is a valid value: lazy initialization, the absence of a "not set" value for a type, etc. It is not always possible to get rid of null. So the recommendation comes down to "try not to use null if it is possible." - Athari
  • This is yes, there are cases when null valid. Then, probably, the first question should be: is null valid at this point? If so, you need a null check and an adequate response. If not, then the code is correct, and the problem is somewhere before (most likely in the initialization). - VladD
  • c # 6.0 null propagation: ref1?.ref2?.ref3?.member - AK

In addition to the @Discord @Squidward @Athari answer, let's look at the question from the other side.

If you had a NullReferenceException while NullReferenceException when accessing a link, you should first ask yourself an important question:

Does this link have the right to be null ?

In many cases, the correct answer is “no,” which means that you will have to correct the true cause of the error, which is in a different place, and happened earlier.

Example: if you have this class:

 class Car { Engine engine; Driver driver; // ... остаток класса } 

So, the motor at the car must be in any case, always. But the driver can, in principle, and not sit in the car.

Therefore, if you see that the call to the engine.HorsePower falls with a NullReferenceException , the real problem is that you forgot to initialize the engine in the constructor. Therefore, you need to correct the error not at the point where it falls, but in the place that would really provide a non-zero engine value.

But if the driver.Age application driver.Age , then there is already a problem right at the point of contact, you must first check that driver != null , and then you can contact us.

Thus: if your link at the reference point does not have the right to be null , then you should not add a check to null , thereby "glossing over" the error. You should either not check anything, but fix it in the place where the link should be initialized, or add Debug.Assert , or check for null and throw an exception.

If the link has the right to be null , then in this case it is necessary to correctly handle this case as well.


Important note: If your function is called "outside world", you should not expect that good, correct arguments will be passed to your function. Even if you require that the object that is passed to you is not null , you can still pass the wrong object to you. Therefore, for functions available to external modules, it is necessary to check the arguments for null immediately at the beginning of the code, and throw the necessary exception:

 public decimal ComputePrice(Car car) { if (car == null) throw new ArgumentNullException("car"); // ... 

Where exactly to draw the line between the "inner" and "outer" world, the question is rather nontrivial. Usually this border is the border of the module (assembly), or even that logical part of it, which is your responsibility. Too small fragmentation leads to the repetition of meaningless code (one part of the program does not trust the other and constantly re-checks it). Too large a split leads to the need to keep millions of dependencies in mind (“can I transmit null here or not?”). Use common sense and personal experience.


C # 8 finally introduces a clear distinction between the two cases. For those links that may contain null , a special syntax is #nullable enable ( #nullable enable must be enabled in the file (or in the <NullableContextOptions>enable</NullableContextOptions> project ):

 class Car { Engine engine; // не может быть null Driver? driver; // может быть null // ... остаток класса } 

In this case, the compiler itself will be able to check that you forgot to initialize the value of the engine field and give you a warning.

  • It is very strange to give information about the feature that is only planned in the new version of the language, and in an obsolete form (according to the current plan, the "nullable reference type" with the modifier ? And not the "non-nullable reference type" with the modifier will be entered ! will be used to extract the value, not the variable definition). - Athari
  • @Discord: The latest design notes in which it was mentioned mention an explicit T! . Although you're right, I'll change the link. - VladD
  • @Discord: What's the problem with information about the new feature? - VladD
  • The problem is that the feature is at a very early stage of implementation, so there is a big risk that your information will not only be useless, as it is now, but also frankly incorrect when the feature is finally implemented. / Modifier ! when declared is discussed only in the context of parameters of generic types. As I understand it, your example should be of the form Engine engine; Driver? driver; Engine engine; Driver? driver; . - Athari
  • @Discord: Perhaps the relevance will be lost. But I will correct the answer as soon as new information becomes known. - VladD

Protected by member Athari 7 May '15 at 12:55 .

Thank you for your interest in this issue. Since he collected a large number of low-quality and spam responses, which had to be deleted, now it’s necessary to have 10 reputation points on the site (the bonus for account association is not counted ).

Maybe you want to answer one of the unanswered questions ?