Ошибка null reference exception

Причина

Вкратце

Вы пытаетесь воспользоваться чем-то, что равно null (или Nothing в VB.NET). Это означает, что либо вы присвоили это значение, либо вы ничего не присваивали.

Как и любое другое значение, null может передаваться от объекта к объекту, от метода к методу. Если нечто равно null в методе «А», вполне может быть, что метод «В» передал это значение в метод «А».

Остальная часть статьи описывает происходящее в деталях и перечисляет распространённые ошибки, которые могут привести к исключению NullReferenceException.

Более подробно

Если среда выполнения выбрасывает исключение NullReferenceException, то это всегда означает одно: вы пытаетесь воспользоваться ссылкой. И эта ссылка не инициализирована (или была инициализирована, но уже не инициализирована).

Это означает, что ссылка равна null, а вы не сможете вызвать методы через ссылку, равную null. В простейшем случае:

string foo = null;
foo.ToUpper();

Этот код выбросит исключение NullReferenceException на второй строке, потому что вы не можете вызвать метод ToUpper() у ссылки на string, равной null.

Отладка

Как определить источник ошибки? Кроме изучения, собственно, исключения, которое будет выброшено именно там, где оно произошло, вы можете воспользоваться общими рекомендациями по отладке в Visual Studio: поставьте точки останова в ключевых точках, изучите значения переменных, либо расположив курсор мыши над переменной, либо открыв панели для отладки: Watch, Locals, Autos.

Если вы хотите определить место, где значение ссылки устанавливается или не устанавливается, нажмите правой кнопкой на её имени и выберите «Find All References». Затем вы можете поставить точки останова на каждой найденной строке и запустить приложение в режиме отладки. Каждый раз, когда отладчик остановится на точке останова, вы можете удостовериться, что значение верное.

Следя за ходом выполнения программы, вы придёте к месту, где значение ссылки не должно быть null, и определите, почему не присвоено верное значение.

Примеры

Несколько общих примеров, в которых возникает исключение.

Цепочка

ref1.ref2.ref3.member

Если ref1, ref2 или ref3 равно null, вы получите NullReferenceException. Для решения проблемы и определения, что именно равно null, вы можете переписать выражение более простым способом:

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

Например, в цепочке HttpContext.Current.User.Identity.Name, значение может отсутствовать и у HttpContext.Current, и у User, и у Identity.

Неявно

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.
    }
}

То же верно для вложенных инициализаторов:

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

Несмотря на использование ключевого слова new, создаётся только экземпляр класса Book, но экземпляр Person не создаётся, поэтому свойство Author остаётся null.

Массив

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

Элементы массива

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

Массив массивов

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.

События

public class Demo
{
    public event EventHandler StateChanged;

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

Неудачное именование переменных

Если бы в коде ниже у локальных переменных и полей были разные имена, вы бы обнаружили, что поле не было инициализировано:

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

Можно избежать проблемы, если использовать префикс для полей:

private Customer _customer;

Цикл жизни страницы ASP.NET

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

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

Пустые вью-модели ASP.NET MVC

Если вы возвращаете пустую модель (или свойство модели) в контроллере, то вью бросит исключение при попытке доступа к ней:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Модель не задана.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Исключение.
{
}

Способы избежать

Явно проверять на null, пропускать код

Если вы ожидаете, что ссылка в некоторых случаях будет равна null, вы можете явно проверить на это значение перед доступом к членам экземпляра:

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

Явно проверять на null, использовать значение по умолчанию

Методы могут возвращать null, например, если не найден требуемый экземпляр. В этом случае вы можете вернуть значение по умолчанию:

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

Явно проверять на null, выбрасывать своё исключение

Вы также можете бросать своё исключение, чтобы позже его поймать:

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

Использовать Debug.Assert для проверки на null для обнаружения ошибки до бросания исключения

Если во время разработки вы знаете, что метод может, но вообще-то не должен возвращать null, вы можете воспользоваться Debug.Assert для быстрого обнаружения ошибки:

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 в режиме отладки.
}

Однако эта проверка не будет работать в релизной сборке, и вы снова получите NullReferenceException, если book == null.

Использовать GetValueOrDefault() для Nullable типов

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

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

Использовать оператор ?? (C#) или If() (VB)

Краткая запись для задания значения по умолчанию:

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

Использовать операторы ?. и ?[ (C# 6+, VB.NET 14+):

Это оператор безопасного доступа к членам, также известный как оператор Элвиса за специфическую форму. Если выражение слева от оператора равно null, то правая часть игнорируется, и результатом считается null. Например:

var title = person.Title.ToUpper();

Если свойство Title равно null, то будет брошено исключение, потому что это попытка вызвать метод ToUpper на значении, равном null. В C# 5 и ниже можно добавить проверку:

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

Теперь вместо бросания исключения переменной title будет присвоено null. В C# 6 был добавлен более короткий синтаксис:

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

Разумеется, если переменная person может быть равна null, то надо проверять и её. Также можно использовать операторы ?. и ?? вместе, чтобы предоставить значение по умолчанию:

// обычная проверка на null
int titleLength = 0;
if (title != null)
    titleLength = title.Length;

// совмещаем операторы `?.` и `??`
int titleLength = title?.Length ?? 0;

Если любой член в цепочке может быть null, то можно полностью обезопасить себя (хотя, конечно, архитектуру стоит поставить под сомнение):

int firstCustomerOrderCount = customers?[0]?.Orders?.Count() ?? 0;

Debugging System.NullReferenceException — Object reference not set to an instance of an object

TOC

Time for another post in the series Debugging common .NET exceptions. Today’s exception is, without a doubt, the error most people have experienced: System.NullReferenceException. The exception happens when you try to invoke a reference that you were expecting to point to an object but in fact, points to null. Let’s get started!

Debugging System.NullReferenceException - Object reference not set to an instance of an object

Handling the error

There are some clever ways to avoid a NullReferenceException, but before we start looking into those, let us see how the exception can be caught. Being a plain old C# exception, NullReferenceException can be caught using a try/catch:

try
{
    string s = null;
    s.ToString();
}
catch (NullReferenceException e)
{
    // Do something with e, please.
}

Running the code above will produce the following error:

System.NullReferenceException: Object reference not set to an instance of an object.

Debugging the error

We already know why the exception is happening. Something is null. When looking at the code above, it’s clear that s is null and the stack trace even tells us that:

stacktrace_1571989670

Sometimes spotting what is null can be hard. Take a look at the following example:

var street = service.GetUser().Address.Street;

If the code above throws a NullReferenceException, what is null? service? The result of GetUser()? Address? At first glance, Visual Studio isn’t exactly helpful either:

NullReferenceException in Visual Studio

There is a range of different ways to find out what is going on. Let’s look at the most commonly used ones.

Splitting chained method-calls to multiple lines

Spotting which call that caused an error is a lot easier if the calls are split into multiple lines:

var service = new Service();
var user = service.GetUser();
var address = user.Address;
var street = address.Street;

Running the code reveals the actual call causing the exception:

NullReferenceException in Visual Studio 2

In the example above user.Address returns null, why address.Street causes the NullReferenceException.

While splitting code into atoms like this can help debug what is going wrong, it’s not preferable in terms of readability (IMO).

Using Null Reference Analysis in Visual Studio

If you are on Visual Studio 2017 or newer (if not, now is the time to upgrade), you will have the Null Reference Analysis feature available. With this in place, Visual Studio can show you exactly what is null. Let’s change the example back to method-chaining:

var street = service.GetUser().Address.Street;

To enable the analysis go to Debug | Windows | Exception Settings. Check Common Language Runtime Exceptions (if not already checked) or extend the node and check the exceptions you are interested in. In this case, you can check System.NullReferenceException. When running the code, the debugger breaks on the NullReferenceException and you now see the Exception Thrown window:

Exception Thrown Window

Voila! The window says «ConsoleApp18.User.Address.get returned null». Exactly what we wanted to see. This will require you to run the code locally, though. If you are experiencing the exception on your production website, the Null Reference Analysis will not be available, since this is a feature belonging to Visual Studio (unfortunately). With that said, you can attach a debugger to a remote site running on Azure as explained here: Introduction to Remote Debugging on Azure Web Sites.

Fixing the error

There are various ways to fix NullReferenceException. We’ll start with the simple (but dirty) approach.

Using null checks

If null is an allowed value of an object, you will need to check for it. The most simple solution is to include a bunch of if-statements.

if (service != null)
{
    var user = service.GetUser();
    if (user != null)
    {
        var address = user.Address;
        if (address != null)
        {
            var street = address.Street;
        }
    }
}

The previous code will only reach address.Street if everything else is not null. We can probably agree that the code isn’t exactly pretty. Having multiple nested steps is harder to read. We can reverse the if-statements:

if (service == null) return;
var user = service.GetUser();
if (user == null) return;
var address = user.Address;
if (address == null) return;
var street = address.Street;

Simpler, but still a lot of code to get a street name.

Using null-conditional operator

C# 6 introduced a piece of syntactic sugar to check for null: null-conditional operator. Let’s change the method-chain example from before to use the «new» operator:

var user = service?.GetUser()?.Address?.Street;

The ? to the right of each variable, corresponds the nested if-statements from previously. But with much less code.

Use Debug.Assert during development

When getting a NullReferenceException it can be hard to spot the intent with the code from the original developer. Rather than including if-statements, it can be clearer for future authors of your code to use the Debug.Assert-method. Much like in a xUnit or NUnit test, you use Assert to verify the desired state on your objects. In the example from above, the service object could have come through a parameter or a constructor injected dependency:

class MyClass
{
    Service service;
    
    public MyClass(Service service)
    {
        this.service = service;
    }
    
    public string UserStreet()
    {
        return service.GetUser().Address.Street;
    }
}

To make a statement in your code that service should never be allowed to have the value of null, extend the constructor:

public MyClass(Service service)
{
    Debug.Assert(service != null);
    this.service = service;
}

In the case MyClass is constructed with null, the following error is shown when running locally:

Assert error

Use nullable reference types in C# 8.0

When designing code you often end up expecting parameters to be not null but end up checking for null to avoid a NullReferenceException. As you already know, all reference types in C# can take the value of null. Value types like int and boolean cannot take a value of null unless explicitely specified using the nullable value type (int? or Nullable<int>). Maybe it should have been the other way around with reference types all along?

C# 8 can fix this with nullable reference types (maybe NOT nullable reference types is a better name). Since this is a breaking change, it is launched as an opt-in feature. Nullable reference types are a great way to avoid NullReferenceExceptions, since you are very explicit about where you expect null and where not.

To enable not nullable reference types, create a new .NET Core 3 project and add the following to the csproj file:

<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>

You should be on C# 8 already, but to make it explicit, I’ve added the LangVersion element. The Nullable element enables nullable reference types. Out of the box, C# 8 creates a warning if it identifies the use of null where a value is expected. Let’s see how that looks:

class Program
{
    static void Main()
    {
        new Program().SayHello(null);
    }

    public void SayHello(string msg)
    {
        Console.WriteLine(msg);
    }
}

When compiling we see the following warning:

Program.cs(9,36): warning CS8625: Cannot convert null literal to non-nullable reference type. [C:projectscore3core3.csproj]

I know you are not one of them, but some people developed a warning-resistance which means that warnings are simply ignored. To overcome this, make sure that errors like this causes build errors over warnings by adding the following to csproj:

<WarningsAsErrors>CS8602,CS8603,CS8618,CS8625</WarningsAsErrors>

This will tell the C# compiler to treat these four nullable reference type warnings as errors instead.

Just to make it clear, allowing null in the msg parameter, you use the ? characters as with value types:

public void SayHello(string? msg)
{
    ...
}

Logging and monitoring

Logging and monitoring for null reference exceptions are a must. While some developers tempt to create control flow from exceptions (no-one should), null reference exceptions should never happen. This means that a System.NullReferenceException is a type of exception that should always be logged and fixed. A null check through either an if statement or the null-conditional operator is always the preferred way of handling potential null values. But make sure to implement a logging strategy that logs all uncaught exceptions, including the System.NullReferenceException.

When logging a System.NullReferenceException in a log file, database, elmah.io, or similar, it can be hard to spot what is null. You typically only see the method-name that causes the NullReferenceException and the Null Reference Analysis feature is only available while debugging inside Visual Studio. I will recommend you to always Include filename and line number in stack traces. This will pinpoint the exact line where the error happens.

elmah.io: Error logging and Uptime Monitoring for your web apps

This blog post is brought to you by elmah.io. elmah.io is error logging, uptime monitoring, deployment tracking, and service heartbeats for your .NET and JavaScript applications. Stop relying on your users to notify you when something is wrong or dig through hundreds of megabytes of log files spread across servers. With elmah.io, we store all of your log messages, notify you through popular channels like email, Slack, and Microsoft Teams, and help you fix errors fast.

elmah.io app banner

See how we can help you monitor your website for crashes
Monitor your website

A NullReferenceException happens when you try to access a reference variable that isn’t referencing any object. If a reference variable isn’t referencing an object, then it’ll be treated as null. The run-time will tell you that you are trying to access an object, when the variable is null by issuing a NullReferenceException.

Reference variables in c# and JavaScript are similar in concept to pointers in C and C++. Reference types default to null to indicate that they are not referencing any object. Hence, if you try and access the object that is being referenced and there isn’t one, you will get a NullReferenceException.

When you get a NullReferenceException in your code it means that you have forgotten to set a variable before using it. The error message will look something like:

NullReferenceException: Object reference not set to an instance of an object
  at Example.Start () [0x0000b] in /Unity/projects/nre/Assets/Example.cs:10 

This error message says that a NullReferenceException happened on line 10 of the script file Example.cs. Also, the message says that the exception happened inside the Start() function. This makes the Null Reference Exception easy to find and fix. In this example, the code is:

//c# example
using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    // Use this for initialization
    void Start () {
        __GameObject__The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject's functionality is defined by the Components attached to it. [More info](class-GameObject.html)<span class="tooltipGlossaryLink">See in [Glossary](Glossary.html#GameObject)</span> go = GameObject.Find("wibble");
        Debug.Log(go.name);
    }

}

The code simply looks for a game object called “wibble”. In this example there is no game object with that name, so the Find() function returns null. On the next line (line 9) we use the go variable and try and print out the name of the game object it references. Because we are accessing a game object that doesn’t exist the run-time gives us a NullReferenceException

Null Checks

Although it can be frustrating when this happens it just means the script needs to be more careful. The solution in this simple example is to change the code like this:

using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    void Start () {
        GameObject go = GameObject.Find("wibble");
        if (go) {
            Debug.Log(go.name);
        } else {
            Debug.Log("No game object called wibble found");
        }
    }

}

Now, before we try and do anything with the go variable, we check to see that it is not null. If it is null, then we display a message.

Try/Catch Blocks

Another cause for NullReferenceException is to use a variable that should be initialised in the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary
. If you forget to do this, then the variable will be null. A different way to deal with NullReferenceException is to use try/catch block. For example, this code:

using UnityEngine;
using System;
using System.Collections;

public class Example2 : MonoBehaviour {

    public Light myLight; // set in the inspector

    void Start () {
        try {
            myLight.color = Color.yellow;
        }       
        catch (NullReferenceException ex) {
            Debug.Log("myLight was not set in the inspector");
        }
    }

}

In this code example, the variable called myLight is a Light which should be set in the Inspector window. If this variable is not set, then it will default to null. Attempting to change the color of the light in the try block causes a NullReferenceException which is picked up by the catch block. The catch block displays a message which might be more helpful to artists and game designers, and reminds them to set the light in the inspector.

Summary

  • NullReferenceException happens when your script code tries to use a variable which isn’t set (referencing) and object.
  • The error message that appears tells you a great deal about where in the code the problem happens.
  • NullReferenceException can be avoided by writing code that checks for null before accessing an object, or uses try/catch blocks.

Причина

Вкратце

Вы пытаетесь воспользоваться чем-то, что равно null (или Nothing в VB.NET). Это означает, что либо вы присвоили это значение, либо вы ничего не присваивали.

Как и любое другое значение, null может передаваться от объекта к объекту, от метода к методу. Если нечто равно null в методе «А», вполне может быть, что метод «В» передал это значение в метод «А».

Остальная часть статьи описывает происходящее в деталях и перечисляет распространённые ошибки, которые могут привести к исключению NullReferenceException.

Более подробно

Если среда выполнения выбрасывает исключение NullReferenceException, то это всегда означает одно: вы пытаетесь воспользоваться ссылкой. И эта ссылка не инициализирована (или была инициализирована, но уже не инициализирована).

Это означает, что ссылка равна null, а вы не сможете вызвать методы через ссылку, равную null. В простейшем случае:

string foo = null;
foo.ToUpper();

Этот код выбросит исключение NullReferenceException на второй строке, потому что вы не можете вызвать метод ToUpper() у ссылки на string, равной null.

Отладка

Как определить источник ошибки? Кроме изучения, собственно, исключения, которое будет выброшено именно там, где оно произошло, вы можете воспользоваться общими рекомендациями по отладке в Visual Studio: поставьте точки останова в ключевых точках, изучите значения переменных, либо расположив курсор мыши над переменной, либо открыв панели для отладки: Watch, Locals, Autos.

Если вы хотите определить место, где значение ссылки устанавливается или не устанавливается, нажмите правой кнопкой на её имени и выберите «Find All References». Затем вы можете поставить точки останова на каждой найденной строке и запустить приложение в режиме отладки. Каждый раз, когда отладчик остановится на точке останова, вы можете удостовериться, что значение верное.

Следя за ходом выполнения программы, вы придёте к месту, где значение ссылки не должно быть null, и определите, почему не присвоено верное значение.

Примеры

Несколько общих примеров, в которых возникает исключение.

Цепочка

ref1.ref2.ref3.member

Если ref1, ref2 или ref3 равно null, вы получите NullReferenceException. Для решения проблемы и определения, что именно равно null, вы можете переписать выражение более простым способом:

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

Например, в цепочке HttpContext.Current.User.Identity.Name, значение может отсутствовать и у HttpContext.Current, и у User, и у Identity.

Неявно

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.
    }
}

То же верно для вложенных инициализаторов:

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

Несмотря на использование ключевого слова new, создаётся только экземпляр класса Book, но экземпляр Person не создаётся, поэтому свойство Author остаётся null.

Массив

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

Элементы массива

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

Массив массивов

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.

События

public class Demo
{
    public event EventHandler StateChanged;

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

Неудачное именование переменных

Если бы в коде ниже у локальных переменных и полей были разные имена, вы бы обнаружили, что поле не было инициализировано:

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

Можно избежать проблемы, если использовать префикс для полей:

private Customer _customer;

Цикл жизни страницы ASP.NET

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

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

Пустые вью-модели ASP.NET MVC

Если вы возвращаете пустую модель (или свойство модели) в контроллере, то вью бросит исключение при попытке доступа к ней:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Модель не задана.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Исключение.
{
}

Способы избежать

Явно проверять на null, пропускать код

Если вы ожидаете, что ссылка в некоторых случаях будет равна null, вы можете явно проверить на это значение перед доступом к членам экземпляра:

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

Явно проверять на null, использовать значение по умолчанию

Методы могут возвращать null, например, если не найден требуемый экземпляр. В этом случае вы можете вернуть значение по умолчанию:

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

Явно проверять на null, выбрасывать своё исключение

Вы также можете бросать своё исключение, чтобы позже его поймать:

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

Использовать Debug.Assert для проверки на null для обнаружения ошибки до бросания исключения

Если во время разработки вы знаете, что метод может, но вообще-то не должен возвращать null, вы можете воспользоваться Debug.Assert для быстрого обнаружения ошибки:

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 в режиме отладки.
}

Однако эта проверка не будет работать в релизной сборке, и вы снова получите NullReferenceException, если book == null.

Использовать GetValueOrDefault() для Nullable типов

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

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

Использовать оператор ?? (C#) или If() (VB)

Краткая запись для задания значения по умолчанию:

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

Использовать операторы ?. и ?[ (C# 6+, VB.NET 14+):

Это оператор безопасного доступа к членам, также известный как оператор Элвиса за специфическую форму. Если выражение слева от оператора равно null, то правая часть игнорируется, и результатом считается null. Например:

var title = person.Title.ToUpper();

Если свойство Title равно null, то будет брошено исключение, потому что это попытка вызвать метод ToUpper на значении, равном null. В C# 5 и ниже можно добавить проверку:

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

Теперь вместо бросания исключения переменной title будет присвоено null. В C# 6 был добавлен более короткий синтаксис:

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

Разумеется, если переменная person может быть равна null, то надо проверять и её. Также можно использовать операторы ?. и ?? вместе, чтобы предоставить значение по умолчанию:

// обычная проверка на null
int titleLength = 0;
if (title != null)
    titleLength = title.Length;

// совмещаем операторы `?.` и `??`
int titleLength = title?.Length ?? 0;

Если любой член в цепочке может быть null, то можно полностью обезопасить себя (хотя, конечно, архитектуру стоит поставить под сомнение):

int firstCustomerOrderCount = customers?[0]?.Orders?.Count() ?? 0;

NullReference Exception — Visual Basic

The NullReference Exception for Visual Basic is no different from the one in C#. After all, they are both reporting the same exception defined in the .NET Framework which they both use. Causes unique to Visual Basic are rare (perhaps only one).

This answer will use Visual Basic terms, syntax, and context. The examples used come from a large number of past Stack  Overflow questions. This is to maximize relevance by using the kinds of situations often seen in posts. A bit more explanation is also provided for those who might need it. An example similar to yours is very likely listed here.

Note:

  1. This is concept-based: there is no code for you to paste into your project. It is intended to help you understand what causes a NullReferenceException (NRE), how to find it, how to fix it, and how to avoid it. An NRE can be caused many ways so this is unlikely to be your sole encounter.
  2. The examples (from Stack  Overflow posts) do not always show the best way to do something in the first place.
  3. Typically, the simplest remedy is used.

Basic Meaning

The message «Object not set to an instance of Object» means you are trying to use an object which has not been initialized. This boils down to one of these:

  • Your code declared an object variable, but it did not initialize it (create an instance or ‘instantiate‘ it)
  • Something which your code assumed would initialize an object, did not
  • Possibly, other code prematurely invalidated an object still in use

Finding The Cause

Since the problem is an object reference which is Nothing, the answer is to examine them to find out which one. Then determine why it is not initialized. Hold the mouse over the various variables and Visual Studio (VS) will show their values — the culprit will be Nothing.

IDE debug display

You should also remove any Try/Catch blocks from the relevant code, especially ones where there is nothing in the Catch block. This will cause your code to crash when it tries to use an object which is Nothing. This is what you want because it will identify the exact location of the problem, and allow you to identify the object causing it.

A MsgBox in the Catch which displays Error while... will be of little help. This method also leads to very bad Stack  Overflow questions, because you can’t describe the actual exception, the object involved or even the line of code where it happens.

You can also use the Locals Window (Debug -> Windows -> Locals) to examine your objects.

Once you know what and where the problem is, it is usually fairly easy to fix and faster than posting a new question.

See also:

  • Breakpoints
  • MSDN: How to: Use the Try/Catch Block to Catch Exceptions
  • MSDN: Best Practices for Exceptions

Examples and Remedies

Class Objects / Creating an Instance

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

The problem is that Dim does not create a CashRegister object; it only declares a variable named reg of that Type. Declaring an object variable and creating an instance are two different things.

Remedy

The New operator can often be used to create the instance when you declare it:

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

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

When it is only appropriate to create the instance later:

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

Note: Do not use Dim again in a procedure, including the constructor (Sub New):

Private reg As CashRegister
'...

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

This will create a local variable, reg, which exists only in that context (sub). The reg variable with module level Scope which you will use everywhere else remains Nothing.

Missing the New operator is the #1 cause of NullReference Exceptions seen in the Stack  Overflow questions reviewed.

Visual Basic tries to make the process clear repeatedly using New: Using the New Operator creates a new object and calls Sub New — the constructor — where your object can perform any other initialization.

To be clear, Dim (or Private) only declares a variable and its Type. The Scope of the variable — whether it exists for the entire module/class or is local to a procedure — is determined by where it is declared. Private | Friend | Public defines the access level, not Scope.

For more information, see:

  • New Operator
  • Scope in Visual Basic
  • Access Levels in Visual Basic
  • Value Types and Reference Types

Arrays

Arrays must also be instantiated:

Private arr as String()

This array has only been declared, not created. There are several ways to initialize an array:

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

Note: Beginning with VS 2010, when initializing a local array using a literal and Option Infer, the As <Type> and New elements are optional:

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}

The data Type and array size are inferred from the data being assigned. Class/Module level declarations still require As <Type> with Option Strict:

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

Example: Array of class objects

Dim arrFoo(5) As Foo

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

The array has been created, but the Foo objects in it have not.

Remedy

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

Using a List(Of T) will make it quite difficult to have an element without a valid object:

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

For more information, see:

  • Option Infer Statement
  • Scope in Visual Basic
  • Arrays in Visual Basic

Lists and Collections

.NET collections (of which there are many varieties — Lists, Dictionary, etc.) must also be instantiated or created.

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

You get the same exception for the same reason — myList was only declared, but no instance created. The remedy is the same:

myList = New List(Of String)

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

A common oversight is a class which uses a collection 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

Either procedure will result in an NRE, because barList is only declared, not instantiated. Creating an instance of Foo will not also create an instance of the internal barList. It may have been the intent to do this in the constructor:

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

As before, this is incorrect:

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

For more information, see List(Of T) Class.


Data Provider Objects

Working with databases presents many opportunities for a NullReference because there can be many objects (Command, Connection, Transaction, Dataset, DataTable, DataRows….) in use at once. Note: It does not matter which data provider you are using — MySQL, SQL Server, OleDB, etc. — the concepts are the same.

Example 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

As before, the ds Dataset object was declared, but an instance was never created. The DataAdapter will fill an existing DataSet, not create one. In this case, since ds is a local variable, the IDE warns you that this might happen:

img

When declared as a module/class level variable, as appears to be the case with con, the compiler can’t know if the object was created by an upstream procedure. Do not ignore warnings.

Remedy

Dim ds As New DataSet

Example 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)

A typo is a problem here: Employees vs Employee. There was no DataTable named «Employee» created, so a NullReferenceException results trying to access it. Another potential problem is assuming there will be Items which may not be so when the SQL includes a WHERE clause.

Remedy

Since this uses one table, using Tables(0) will avoid spelling errors. Examining Rows.Count can also help:

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 is a function returning the number of Rows affected which can also be tested:

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

Example 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

The DataAdapter will provide TableNames as shown in the previous example, but it does not parse names from the SQL or database table. As a result, ds.Tables("TICKET_RESERVATION") references a non-existent table.

The Remedy is the same, reference the table by index:

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

See also DataTable Class.


Object Paths / Nested

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

The code is only testing Items while both myFoo and Bar may also be Nothing. The remedy is to test the entire chain or path of objects one at a time:

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

AndAlso is important. Subsequent tests will not be performed once the first False condition is encountered. This allows the code to safely ‘drill’ into the object(s) one ‘level’ at a time, evaluating myFoo.Bar only after (and if) myFoo is determined to be valid. Object chains or paths can get quite long when coding complex objects:

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

It is not possible to reference anything ‘downstream’ of a null object. This also applies to controls:

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

Here, myWebBrowser or Document could be Nothing or the formfld1 element may not exist.


UI Controls

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)

Among other things, this code does not anticipate that the user may not have selected something in one or more UI controls. ListBox1.SelectedItem may well be Nothing, so ListBox1.SelectedItem.ToString will result in an NRE.

Remedy

Validate data before using it (also use Option Strict and SQL parameters):

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

Alternatively, you can use (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

This is a fairly common way to get an NRE. In C#, depending on how it is coded, the IDE will report that Controls does not exist in the current context, or «cannot reference non-static member». So, to some extent, this is a VB-only situation. It is also complex because it can result in a failure cascade.

The arrays and collections cannot be initialized this way. This initialization code will run before the constructor creates the Form or the Controls. As a result:

  • Lists and Collection will simply be empty
  • The Array will contain five elements of Nothing
  • The somevar assignment will result in an immediate NRE because Nothing doesn’t have a .Text property

Referencing array elements later will result in an NRE. If you do this in Form_Load, due to an odd bug, the IDE may not report the exception when it happens. The exception will pop up later when your code tries to use the array. This «silent exception» is detailed in this post. For our purposes, the key is that when something catastrophic happens while creating a form (Sub New or Form Load event), exceptions may go unreported, the code exits the procedure and just displays the form.

Since no other code in your Sub New or Form Load event will run after the NRE, a great many other things can be left uninitialized.

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

Note this applies to any and all control and component references making these illegal where they are:

Public Class Form1

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

Partial Remedy

It is curious that VB does not provide a warning, but the remedy is to declare the containers at the form level, but initialize them in form load event handler when the controls do exist. This can be done in Sub New as long as your code is after the InitializeComponent call:

' 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

The array code may not be out of the woods yet. Any controls which are in a container control (like a GroupBox or Panel) will not be found in Me.Controls; they will be in the Controls collection of that Panel or GroupBox. Nor will a control be returned when the control name is misspelled ("TeStBox2"). In such cases, Nothing will again be stored in those array elements and an NRE will result when you attempt to reference it.

These should be easy to find now that you know what you are looking for:
VS shows you the error of your ways

«Button2» resides on a Panel

Remedy

Rather than indirect references by name using the form’s Controls collection, use the control reference:

' 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...})

Function Returning Nothing

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

This is a case where the IDE will warn you that ‘not all paths return a value and a NullReferenceException may result‘. You can suppress the warning, by replacing Exit Function with Return Nothing, but that does not solve the problem. Anything which tries to use the return when someCondition = False will result in an NRE:

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

Remedy

Replace Exit Function in the function with Return bList. Returning an empty List is not the same as returning Nothing. If there is a chance that a returned object can be Nothing, test before using it:

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

Poorly Implemented Try/Catch

A badly implemented Try/Catch can hide where the problem is and result in new ones:

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

This is a case of an object not being created as expected, but also demonstrates the counter usefulness of an empty Catch.

There is an extra comma in the SQL (after ‘mailaddress’) which results in an exception at .ExecuteReader. After the Catch does nothing, Finally tries to perform clean up, but since you cannot Close a null DataReader object, a brand new NullReferenceException results.

An empty Catch block is the devil’s playground. This OP was baffled why he was getting an NRE in the Finally block. In other situations, an empty Catch may result in something else much further downstream going haywire and cause you to spend time looking at the wrong things in the wrong place for the problem. (The «silent exception» described above provides the same entertainment value.)

Remedy

Don’t use empty Try/Catch blocks — let the code crash so you can a) identify the cause b) identify the location and c) apply a proper remedy. Try/Catch blocks are not intended to hide exceptions from the person uniquely qualified to fix them — the developer.


DBNull is not the same as Nothing

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

The IsDBNull function is used to test if a value equals System.DBNull: From MSDN:

The System.DBNull value indicates that the Object represents missing or non-existent data. DBNull is not the same as Nothing, which indicates that a variable has not yet been initialized.

Remedy

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

As before, you can test for Nothing, then for a specific value:

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

Example 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 returns the first item or the default value, which is Nothing for reference types and never DBNull:

If getFoo IsNot Nothing Then...

Controls

Dim chk As CheckBox

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

If a CheckBox with chkName can’t be found (or exists in a GroupBox), then chk will be Nothing and be attempting to reference any property will result in an exception.

Remedy

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

The DataGridView

The DGV has a few quirks seen periodically:

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"

If dgvBooks has AutoGenerateColumns = True, it will create the columns, but it does not name them, so the above code fails when it references them by name.

Remedy

Name the columns manually, or reference by index:

dgvBooks.Columns(0).Visible = True

Example 2 — Beware of the 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

When your DataGridView has AllowUserToAddRows as True (the default), the Cells in the blank/new row at the bottom will all contain Nothing. Most attempts to use the contents (for example, ToString) will result in an NRE.

Remedy

Use a For/Each loop and test the IsNewRow property to determine if it is that last row. This works whether AllowUserToAddRows is true or not:

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

If you do use a For n loop, modify the row count or use Exit For when IsNewRow is true.


My.Settings (StringCollection)

Under certain circumstances, trying to use an item from My.Settings which is a StringCollection can result in a NullReference the first time you use it. The solution is the same, but not as obvious. Consider:

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

Since VB is managing Settings for you, it is reasonable to expect it to initialize the collection. It will, but only if you have previously added an initial entry to the collection (in the Settings editor). Since the collection is (apparently) initialized when an item is added, it remains Nothing when there are no items in the Settings editor to add.

Remedy

Initialize the settings collection in the form’s Load event handler, if/when needed:

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

Typically, the Settings collection will only need to be initialized the first time the application runs. An alternate remedy is to add an initial value to your collection in Project -> Settings | FooBars, save the project, then remove the fake value.


Key Points

You probably forgot the New operator.

or

Something you assumed would perform flawlessly to return an initialized object to your code, did not.

Don’t ignore compiler warnings (ever) and use Option Strict On (always).


MSDN NullReference Exception

NullReference Exception — Visual Basic

The NullReference Exception for Visual Basic is no different from the one in C#. After all, they are both reporting the same exception defined in the .NET Framework which they both use. Causes unique to Visual Basic are rare (perhaps only one).

This answer will use Visual Basic terms, syntax, and context. The examples used come from a large number of past Stack  Overflow questions. This is to maximize relevance by using the kinds of situations often seen in posts. A bit more explanation is also provided for those who might need it. An example similar to yours is very likely listed here.

Note:

  1. This is concept-based: there is no code for you to paste into your project. It is intended to help you understand what causes a NullReferenceException (NRE), how to find it, how to fix it, and how to avoid it. An NRE can be caused many ways so this is unlikely to be your sole encounter.
  2. The examples (from Stack  Overflow posts) do not always show the best way to do something in the first place.
  3. Typically, the simplest remedy is used.

Basic Meaning

The message «Object not set to an instance of Object» means you are trying to use an object which has not been initialized. This boils down to one of these:

  • Your code declared an object variable, but it did not initialize it (create an instance or ‘instantiate‘ it)
  • Something which your code assumed would initialize an object, did not
  • Possibly, other code prematurely invalidated an object still in use

Finding The Cause

Since the problem is an object reference which is Nothing, the answer is to examine them to find out which one. Then determine why it is not initialized. Hold the mouse over the various variables and Visual Studio (VS) will show their values — the culprit will be Nothing.

IDE debug display

You should also remove any Try/Catch blocks from the relevant code, especially ones where there is nothing in the Catch block. This will cause your code to crash when it tries to use an object which is Nothing. This is what you want because it will identify the exact location of the problem, and allow you to identify the object causing it.

A MsgBox in the Catch which displays Error while... will be of little help. This method also leads to very bad Stack  Overflow questions, because you can’t describe the actual exception, the object involved or even the line of code where it happens.

You can also use the Locals Window (Debug -> Windows -> Locals) to examine your objects.

Once you know what and where the problem is, it is usually fairly easy to fix and faster than posting a new question.

See also:

  • Breakpoints
  • MSDN: How to: Use the Try/Catch Block to Catch Exceptions
  • MSDN: Best Practices for Exceptions

Examples and Remedies

Class Objects / Creating an Instance

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

The problem is that Dim does not create a CashRegister object; it only declares a variable named reg of that Type. Declaring an object variable and creating an instance are two different things.

Remedy

The New operator can often be used to create the instance when you declare it:

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

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

When it is only appropriate to create the instance later:

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

Note: Do not use Dim again in a procedure, including the constructor (Sub New):

Private reg As CashRegister
'...

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

This will create a local variable, reg, which exists only in that context (sub). The reg variable with module level Scope which you will use everywhere else remains Nothing.

Missing the New operator is the #1 cause of NullReference Exceptions seen in the Stack  Overflow questions reviewed.

Visual Basic tries to make the process clear repeatedly using New: Using the New Operator creates a new object and calls Sub New — the constructor — where your object can perform any other initialization.

To be clear, Dim (or Private) only declares a variable and its Type. The Scope of the variable — whether it exists for the entire module/class or is local to a procedure — is determined by where it is declared. Private | Friend | Public defines the access level, not Scope.

For more information, see:

  • New Operator
  • Scope in Visual Basic
  • Access Levels in Visual Basic
  • Value Types and Reference Types

Arrays

Arrays must also be instantiated:

Private arr as String()

This array has only been declared, not created. There are several ways to initialize an array:

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

Note: Beginning with VS 2010, when initializing a local array using a literal and Option Infer, the As <Type> and New elements are optional:

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}

The data Type and array size are inferred from the data being assigned. Class/Module level declarations still require As <Type> with Option Strict:

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

Example: Array of class objects

Dim arrFoo(5) As Foo

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

The array has been created, but the Foo objects in it have not.

Remedy

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

Using a List(Of T) will make it quite difficult to have an element without a valid object:

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

For more information, see:

  • Option Infer Statement
  • Scope in Visual Basic
  • Arrays in Visual Basic

Lists and Collections

.NET collections (of which there are many varieties — Lists, Dictionary, etc.) must also be instantiated or created.

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

You get the same exception for the same reason — myList was only declared, but no instance created. The remedy is the same:

myList = New List(Of String)

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

A common oversight is a class which uses a collection 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

Either procedure will result in an NRE, because barList is only declared, not instantiated. Creating an instance of Foo will not also create an instance of the internal barList. It may have been the intent to do this in the constructor:

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

As before, this is incorrect:

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

For more information, see List(Of T) Class.


Data Provider Objects

Working with databases presents many opportunities for a NullReference because there can be many objects (Command, Connection, Transaction, Dataset, DataTable, DataRows….) in use at once. Note: It does not matter which data provider you are using — MySQL, SQL Server, OleDB, etc. — the concepts are the same.

Example 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

As before, the ds Dataset object was declared, but an instance was never created. The DataAdapter will fill an existing DataSet, not create one. In this case, since ds is a local variable, the IDE warns you that this might happen:

img

When declared as a module/class level variable, as appears to be the case with con, the compiler can’t know if the object was created by an upstream procedure. Do not ignore warnings.

Remedy

Dim ds As New DataSet

Example 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)

A typo is a problem here: Employees vs Employee. There was no DataTable named «Employee» created, so a NullReferenceException results trying to access it. Another potential problem is assuming there will be Items which may not be so when the SQL includes a WHERE clause.

Remedy

Since this uses one table, using Tables(0) will avoid spelling errors. Examining Rows.Count can also help:

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 is a function returning the number of Rows affected which can also be tested:

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

Example 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

The DataAdapter will provide TableNames as shown in the previous example, but it does not parse names from the SQL or database table. As a result, ds.Tables("TICKET_RESERVATION") references a non-existent table.

The Remedy is the same, reference the table by index:

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

See also DataTable Class.


Object Paths / Nested

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

The code is only testing Items while both myFoo and Bar may also be Nothing. The remedy is to test the entire chain or path of objects one at a time:

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

AndAlso is important. Subsequent tests will not be performed once the first False condition is encountered. This allows the code to safely ‘drill’ into the object(s) one ‘level’ at a time, evaluating myFoo.Bar only after (and if) myFoo is determined to be valid. Object chains or paths can get quite long when coding complex objects:

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

It is not possible to reference anything ‘downstream’ of a null object. This also applies to controls:

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

Here, myWebBrowser or Document could be Nothing or the formfld1 element may not exist.


UI Controls

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)

Among other things, this code does not anticipate that the user may not have selected something in one or more UI controls. ListBox1.SelectedItem may well be Nothing, so ListBox1.SelectedItem.ToString will result in an NRE.

Remedy

Validate data before using it (also use Option Strict and SQL parameters):

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

Alternatively, you can use (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

This is a fairly common way to get an NRE. In C#, depending on how it is coded, the IDE will report that Controls does not exist in the current context, or «cannot reference non-static member». So, to some extent, this is a VB-only situation. It is also complex because it can result in a failure cascade.

The arrays and collections cannot be initialized this way. This initialization code will run before the constructor creates the Form or the Controls. As a result:

  • Lists and Collection will simply be empty
  • The Array will contain five elements of Nothing
  • The somevar assignment will result in an immediate NRE because Nothing doesn’t have a .Text property

Referencing array elements later will result in an NRE. If you do this in Form_Load, due to an odd bug, the IDE may not report the exception when it happens. The exception will pop up later when your code tries to use the array. This «silent exception» is detailed in this post. For our purposes, the key is that when something catastrophic happens while creating a form (Sub New or Form Load event), exceptions may go unreported, the code exits the procedure and just displays the form.

Since no other code in your Sub New or Form Load event will run after the NRE, a great many other things can be left uninitialized.

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

Note this applies to any and all control and component references making these illegal where they are:

Public Class Form1

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

Partial Remedy

It is curious that VB does not provide a warning, but the remedy is to declare the containers at the form level, but initialize them in form load event handler when the controls do exist. This can be done in Sub New as long as your code is after the InitializeComponent call:

' 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

The array code may not be out of the woods yet. Any controls which are in a container control (like a GroupBox or Panel) will not be found in Me.Controls; they will be in the Controls collection of that Panel or GroupBox. Nor will a control be returned when the control name is misspelled ("TeStBox2"). In such cases, Nothing will again be stored in those array elements and an NRE will result when you attempt to reference it.

These should be easy to find now that you know what you are looking for:
VS shows you the error of your ways

«Button2» resides on a Panel

Remedy

Rather than indirect references by name using the form’s Controls collection, use the control reference:

' 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...})

Function Returning Nothing

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

This is a case where the IDE will warn you that ‘not all paths return a value and a NullReferenceException may result‘. You can suppress the warning, by replacing Exit Function with Return Nothing, but that does not solve the problem. Anything which tries to use the return when someCondition = False will result in an NRE:

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

Remedy

Replace Exit Function in the function with Return bList. Returning an empty List is not the same as returning Nothing. If there is a chance that a returned object can be Nothing, test before using it:

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

Poorly Implemented Try/Catch

A badly implemented Try/Catch can hide where the problem is and result in new ones:

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

This is a case of an object not being created as expected, but also demonstrates the counter usefulness of an empty Catch.

There is an extra comma in the SQL (after ‘mailaddress’) which results in an exception at .ExecuteReader. After the Catch does nothing, Finally tries to perform clean up, but since you cannot Close a null DataReader object, a brand new NullReferenceException results.

An empty Catch block is the devil’s playground. This OP was baffled why he was getting an NRE in the Finally block. In other situations, an empty Catch may result in something else much further downstream going haywire and cause you to spend time looking at the wrong things in the wrong place for the problem. (The «silent exception» described above provides the same entertainment value.)

Remedy

Don’t use empty Try/Catch blocks — let the code crash so you can a) identify the cause b) identify the location and c) apply a proper remedy. Try/Catch blocks are not intended to hide exceptions from the person uniquely qualified to fix them — the developer.


DBNull is not the same as Nothing

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

The IsDBNull function is used to test if a value equals System.DBNull: From MSDN:

The System.DBNull value indicates that the Object represents missing or non-existent data. DBNull is not the same as Nothing, which indicates that a variable has not yet been initialized.

Remedy

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

As before, you can test for Nothing, then for a specific value:

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

Example 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 returns the first item or the default value, which is Nothing for reference types and never DBNull:

If getFoo IsNot Nothing Then...

Controls

Dim chk As CheckBox

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

If a CheckBox with chkName can’t be found (or exists in a GroupBox), then chk will be Nothing and be attempting to reference any property will result in an exception.

Remedy

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

The DataGridView

The DGV has a few quirks seen periodically:

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"

If dgvBooks has AutoGenerateColumns = True, it will create the columns, but it does not name them, so the above code fails when it references them by name.

Remedy

Name the columns manually, or reference by index:

dgvBooks.Columns(0).Visible = True

Example 2 — Beware of the 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

When your DataGridView has AllowUserToAddRows as True (the default), the Cells in the blank/new row at the bottom will all contain Nothing. Most attempts to use the contents (for example, ToString) will result in an NRE.

Remedy

Use a For/Each loop and test the IsNewRow property to determine if it is that last row. This works whether AllowUserToAddRows is true or not:

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

If you do use a For n loop, modify the row count or use Exit For when IsNewRow is true.


My.Settings (StringCollection)

Under certain circumstances, trying to use an item from My.Settings which is a StringCollection can result in a NullReference the first time you use it. The solution is the same, but not as obvious. Consider:

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

Since VB is managing Settings for you, it is reasonable to expect it to initialize the collection. It will, but only if you have previously added an initial entry to the collection (in the Settings editor). Since the collection is (apparently) initialized when an item is added, it remains Nothing when there are no items in the Settings editor to add.

Remedy

Initialize the settings collection in the form’s Load event handler, if/when needed:

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

Typically, the Settings collection will only need to be initialized the first time the application runs. An alternate remedy is to add an initial value to your collection in Project -> Settings | FooBars, save the project, then remove the fake value.


Key Points

You probably forgot the New operator.

or

Something you assumed would perform flawlessly to return an initialized object to your code, did not.

Don’t ignore compiler warnings (ever) and use Option Strict On (always).


MSDN NullReference Exception

Debugging System.NullReferenceException — Object reference not set to an instance of an object

TOC

Time for another post in the series Debugging common .NET exceptions. Today’s exception is, without a doubt, the error most people have experienced: System.NullReferenceException. The exception happens when you try to invoke a reference that you were expecting to point to an object but in fact, points to null. Let’s get started!

Debugging System.NullReferenceException - Object reference not set to an instance of an object

Handling the error

There are some clever ways to avoid a NullReferenceException, but before we start looking into those, let us see how the exception can be caught. Being a plain old C# exception, NullReferenceException can be caught using a try/catch:

try
{
    string s = null;
    s.ToString();
}
catch (NullReferenceException e)
{
    // Do something with e, please.
}

Running the code above will produce the following error:

System.NullReferenceException: Object reference not set to an instance of an object.

Debugging the error

We already know why the exception is happening. Something is null. When looking at the code above, it’s clear that s is null and the stack trace even tells us that:

stacktrace_1571989670

Sometimes spotting what is null can be hard. Take a look at the following example:

var street = service.GetUser().Address.Street;

If the code above throws a NullReferenceException, what is null? service? The result of GetUser()? Address? At first glance, Visual Studio isn’t exactly helpful either:

NullReferenceException in Visual Studio

There is a range of different ways to find out what is going on. Let’s look at the most commonly used ones.

Splitting chained method-calls to multiple lines

Spotting which call that caused an error is a lot easier if the calls are split into multiple lines:

var service = new Service();
var user = service.GetUser();
var address = user.Address;
var street = address.Street;

Running the code reveals the actual call causing the exception:

NullReferenceException in Visual Studio 2

In the example above user.Address returns null, why address.Street causes the NullReferenceException.

While splitting code into atoms like this can help debug what is going wrong, it’s not preferable in terms of readability (IMO).

Using Null Reference Analysis in Visual Studio

If you are on Visual Studio 2017 or newer (if not, now is the time to upgrade), you will have the Null Reference Analysis feature available. With this in place, Visual Studio can show you exactly what is null. Let’s change the example back to method-chaining:

var street = service.GetUser().Address.Street;

To enable the analysis go to Debug | Windows | Exception Settings. Check Common Language Runtime Exceptions (if not already checked) or extend the node and check the exceptions you are interested in. In this case, you can check System.NullReferenceException. When running the code, the debugger breaks on the NullReferenceException and you now see the Exception Thrown window:

Exception Thrown Window

Voila! The window says «ConsoleApp18.User.Address.get returned null». Exactly what we wanted to see. This will require you to run the code locally, though. If you are experiencing the exception on your production website, the Null Reference Analysis will not be available, since this is a feature belonging to Visual Studio (unfortunately). With that said, you can attach a debugger to a remote site running on Azure as explained here: Introduction to Remote Debugging on Azure Web Sites.

Fixing the error

There are various ways to fix NullReferenceException. We’ll start with the simple (but dirty) approach.

Using null checks

If null is an allowed value of an object, you will need to check for it. The most simple solution is to include a bunch of if-statements.

if (service != null)
{
    var user = service.GetUser();
    if (user != null)
    {
        var address = user.Address;
        if (address != null)
        {
            var street = address.Street;
        }
    }
}

The previous code will only reach address.Street if everything else is not null. We can probably agree that the code isn’t exactly pretty. Having multiple nested steps is harder to read. We can reverse the if-statements:

if (service == null) return;
var user = service.GetUser();
if (user == null) return;
var address = user.Address;
if (address == null) return;
var street = address.Street;

Simpler, but still a lot of code to get a street name.

Using null-conditional operator

C# 6 introduced a piece of syntactic sugar to check for null: null-conditional operator. Let’s change the method-chain example from before to use the «new» operator:

var user = service?.GetUser()?.Address?.Street;

The ? to the right of each variable, corresponds the nested if-statements from previously. But with much less code.

Use Debug.Assert during development

When getting a NullReferenceException it can be hard to spot the intent with the code from the original developer. Rather than including if-statements, it can be clearer for future authors of your code to use the Debug.Assert-method. Much like in a xUnit or NUnit test, you use Assert to verify the desired state on your objects. In the example from above, the service object could have come through a parameter or a constructor injected dependency:

class MyClass
{
    Service service;
    
    public MyClass(Service service)
    {
        this.service = service;
    }
    
    public string UserStreet()
    {
        return service.GetUser().Address.Street;
    }
}

To make a statement in your code that service should never be allowed to have the value of null, extend the constructor:

public MyClass(Service service)
{
    Debug.Assert(service != null);
    this.service = service;
}

In the case MyClass is constructed with null, the following error is shown when running locally:

Assert error

Use nullable reference types in C# 8.0

When designing code you often end up expecting parameters to be not null but end up checking for null to avoid a NullReferenceException. As you already know, all reference types in C# can take the value of null. Value types like int and boolean cannot take a value of null unless explicitely specified using the nullable value type (int? or Nullable<int>). Maybe it should have been the other way around with reference types all along?

C# 8 can fix this with nullable reference types (maybe NOT nullable reference types is a better name). Since this is a breaking change, it is launched as an opt-in feature. Nullable reference types are a great way to avoid NullReferenceExceptions, since you are very explicit about where you expect null and where not.

To enable not nullable reference types, create a new .NET Core 3 project and add the following to the csproj file:

<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>

You should be on C# 8 already, but to make it explicit, I’ve added the LangVersion element. The Nullable element enables nullable reference types. Out of the box, C# 8 creates a warning if it identifies the use of null where a value is expected. Let’s see how that looks:

class Program
{
    static void Main()
    {
        new Program().SayHello(null);
    }

    public void SayHello(string msg)
    {
        Console.WriteLine(msg);
    }
}

When compiling we see the following warning:

Program.cs(9,36): warning CS8625: Cannot convert null literal to non-nullable reference type. [C:projectscore3core3.csproj]

I know you are not one of them, but some people developed a warning-resistance which means that warnings are simply ignored. To overcome this, make sure that errors like this causes build errors over warnings by adding the following to csproj:

<WarningsAsErrors>CS8602,CS8603,CS8618,CS8625</WarningsAsErrors>

This will tell the C# compiler to treat these four nullable reference type warnings as errors instead.

Just to make it clear, allowing null in the msg parameter, you use the ? characters as with value types:

public void SayHello(string? msg)
{
    ...
}

Logging and monitoring

Logging and monitoring for null reference exceptions are a must. While some developers tempt to create control flow from exceptions (no-one should), null reference exceptions should never happen. This means that a System.NullReferenceException is a type of exception that should always be logged and fixed. A null check through either an if statement or the null-conditional operator is always the preferred way of handling potential null values. But make sure to implement a logging strategy that logs all uncaught exceptions, including the System.NullReferenceException.

When logging a System.NullReferenceException in a log file, database, elmah.io, or similar, it can be hard to spot what is null. You typically only see the method-name that causes the NullReferenceException and the Null Reference Analysis feature is only available while debugging inside Visual Studio. I will recommend you to always Include filename and line number in stack traces. This will pinpoint the exact line where the error happens.

elmah.io: Error logging and Uptime Monitoring for your web apps

This blog post is brought to you by elmah.io. elmah.io is error logging, uptime monitoring, deployment tracking, and service heartbeats for your .NET and JavaScript applications. Stop relying on your users to notify you when something is wrong or dig through hundreds of megabytes of log files spread across servers. With elmah.io, we store all of your log messages, notify you through popular channels like email, Slack, and Microsoft Teams, and help you fix errors fast.

elmah.io app banner

See how we can help you monitor your website for crashes
Monitor your website

In C#, a NullReferenceException occurs when we try to access a variable whose value has not been set or has been set to null. It can be easy to trigger this exception accidentally, so it’s important to be aware of how to avoid it in the first place. In this article, we’ll take a look at some common causes of NullReferenceException errors and how to fix them. We’ll also discuss ways to prevent NullReferenceException errors from happening in the first place.

To download the source code for this article, you can visit our GitHub repository.

Without further ado, let’s get started!

What Is a Null Object in C#?

In C#, a null object is an uninitialized object. This means that the object doesn’t have a value (other than null) assigned to it yet. When we create a new object, it’s automatically assigned a null value. We can change this by explicitly assigning a value to the object, but it will remain null until we do so.

Let’s understand what causes the NullReferenceException in C#. 

As the name suggests, the NullReferenceException in C# occurs when we try accessing a null object.

Just like other object references, we can pass null values when we attempt to dereference them or pass them to other methods, which can make it difficult to debug and fix this exception. 

We can get the NullReferenceException thrown in various scenarios, which we’ll now look at.

Forgetting to Instantiate a Reference Type

Forgetting to instantiate a reference type is one of the most common causes of this exception:

public List<string> StudentList() 
{
    List<string> studentList = null;

    studentList.Add("John Doe");

    return studentList;
}

Here, we intend to return a List<string> containing a value “John Doe” to the user but the compiler throws a NullReferenceException when we attempt to run it. 

Next, we can verify that the compiler throws the NullReferenceException successfully:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAListObject_WhenNotInstantiated_VerifyThrowsNullReferenceException()
{
    var studentObj = new ExceptionMethods();

    var studentList = studentObj.StudentList();

    Assert.IsNull(studentList);
}

To fix that error, we simply need to instantiate the studentList object in the right way:

public List<string> FixedStudentList()
{
    var studentList = new List<string>();

    studentList.Add("John Doe");

    return studentList;
}

We can proceed to verify that the FixedStudentList() method works correctly by checking that it returns “John Doe” and is not null:

var studentObj = new ExceptionMethods();

var studentList = studentObj.FixedStudentList();
var student = "John Doe";

Assert.IsNotNull(studentList);
Assert.IsInstanceOfType(studentList, typeof(List<string>));
CollectionAssert.Contains(studentList, student);

Failing to Dimension Arrays Before Initializing Them

We have to dimension arrays before initializing them. Therefore, when we attempt to declare an array without specifying the number of elements it is going to hold, it will result in a NullReferenceException being thrown when we attempt to initialize its values.

Let’s simulate this scenario with an example:

public int[] RandomNumbers()
{
    var rand = new Random();

    int[] numbers = null;

    for (int i = 0; i < numbers.Length; i++) 
    {
        numbers[i] = rand.Next();
    }
 
    return numbers;
}

Here, we try to generate random numbers but we do not specify the number of elements while declaring the array, which throws the NullRefereceException:

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenNotInstantiated_VerifyThrowsNullReferenceException()
{
    var arrayObj = new ExceptionMethods();

    var randomNumbers = arrayObj.RandomNumbers();

    Assert.IsNull(randomNumbers);
}

To fix this error, we need to declare the number of elements before initializing the array:

public int[] FixedRandomNumbers()
{
    var rand = new Random();

    var numbers = new int[50];

    for (int i = 0; i < numbers.Length; i++)
    {
        numbers[i] = rand.Next();
    }

    return numbers;
}

Next, we can also go ahead to verify that the method runs successfully without any errors:

var arrayObj = new ExceptionMethods();

var randomNumbers = arrayObj.FixedRandomNumbers();

Assert.IsNotNull(randomNumbers);
Assert.IsInstanceOfType(randomNumbers, typeof(int[]));          

Assuming a Method Always Returns Non-null Values

As the title suggests, sometimes we may erroneously assume that a method is going to return non-null values. For example, a database table may contain some null values, which we have to account for when implementing our business logic.

Let’s implement a simple class to simulate this scenario:

public class Teacher
{
    public string? FirstName { get; set; }

    public Teacher()
    {
    }

    public Teacher[] AddRange(string[] firstNames)
    {
        var teachers = new Teacher[firstNames.Length];

        for (int i = 0; i < firstNames.Length; i++) 
        {
            teachers[i] = new Teacher(firstNames[i]);
        }
            
        return teachers;
    }

    public Teacher(string firstName)
    {
        this.FirstName = firstName;
    }
}

First, we define a property FirstName that must always have a non-null value when exiting the constructor. The AddRange method takes a string array and returns an object of the type Teacher[]

Next, we are going to implement a simple method to search for a single teacher from the Teacher[] array:

public string Teachers(string searchString)
{
    var personObj = new Teacher();
    
    var people = personObj.AddRange(new string[] { "John", "Mary", "Jane", "Usher", "Andrew", "Grace", "Aston", "Sheila" });
    var result = Array.Find(people, p => p.FirstName == searchString);

    return result.ToString();
}

The Teachers() method takes a string searchString as its sole parameter and uses the inbuilt Array.Find() method to search for it. Since FirstName is a non-nullable property, we are assuming that the method will always return a value.

We can verify that the Teachers method throws a NullReferenceException with this test:

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenSearching_VerifyThrowsNullReferenceException()
{
    var listObj = new ExceptionMethods();

    var searchPerson = listObj.Teachers("Steve");

    Assert.IsNull(searchPerson);
}

To address this problem, we need to ensure that we check for the method’s return value to make sure it is not null:

public string FixedTeachers(string searchString)
{
    var personObj = new Teacher();

    var people = personObj.AddRange(new string[] { "John", "Mary", "Jane", "Usher", "Andrew", "Grace", "Aston", "Sheila" });
    var result = Array.Find(people, p => p.FirstName == searchString);
    if (result != null)
    {
        return result.ToString();
    }
    else
    {
        return $"{searchString} could not be found";
    }
}

We can verify that our fix works by checking whether the FixedTeachers() method returns a string and is not null: 

var listObj = new ExceptionMethods();

var searchPerson = listObj.FixedTeachers("Steve");

Assert.IsNotNull(searchPerson);
Assert.IsInstanceOfType(searchPerson, typeof(string));

Enumerating Arrays Elements With Reference Types

In some cases, we may encounter the NullReferenceException when attempting to process array elements when some of them are null. Let’s try to simulate this scenario with an example:

public string[] CapitalizeNames() 
{
    var names = new string[] { "John", "Mary", null, null, "Andrew", "Grace", "Aston", "Sheila" };

    for (int i = 0; i < names.Length; i++)
    {
        names[i] = names[i].ToUpper();
    }

    return names;
}

The CapitalizeNames() method converts the string elements in the names array to upper-case using the inbuilt string.ToUpper() method. However, since some of the elements are null, attempting to convert them to uppercase throws the NullReferenceException, which we can verify:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenSomeElementsNull_VerifyThrowsNullReferenceException()
{
    var arrayObj = new ExceptionMethods();
    
    var capitalizedNames = arrayObj.CapitalizeNames();
    
    Assert.IsNull(capitalizedNames);
}

To resolve this error, we need to check for null values before calling the string.ToUpper() method. We can make use of the string.Length property or the string.IsNullOrEmpty() method to check if a given array element is null:

public string[] FixedCapitalizeNames()
{
    var names = new string[] { "John", "Mary", null, null, "Andrew", "Grace", "Aston", "Sheila" };

    for(int i = 0; i < names.Length; i++)
    {
        if (!string.IsNullOrEmpty(names[i])) 
        {
            names[i] = names[i].ToUpper();
        }
    }

    return names;
}

We can then proceed to check that our method works without any issues with this test:

var arrayObj = new ExceptionMethods();

var capitalizedNames = arrayObj.FixedCapitalizeNames();

Assert.IsNotNull(capitalizedNames);
CollectionAssert.Contains(capitalizedNames, "JOHN");

Passing Null Arguments to Methods

We can trigger the exception when we attempt to pass null arguments to methods. Just like other reference types, we can pass null objects across different methods. Some methods may validate the arguments they receive and end up throwing the System.ArgumentNullException when they detect null arguments. On the other hand, when the methods fail to check for null arguments they end up throwing the NullReferenceException instead. 

Let’s simulate this scenario with an example:

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

public List<string> PopulateList(List<string> peopleNames) 
{
    var names = new string[] { "John", "Mary", "Andrew", "Grace", "Aston", "Sheila" };

    foreach (var person in names) 
    {
        peopleNames.Add(person);
    }
        
    return peopleNames;
}

The PopulateList() method takes a peopleNames list object and appends the array of elements in the names array to that list before returning it back to the user. Here, we are assuming that the PeopleList() method is going to always receive arguments that are not null. 

Let’s test what happens when we try to pass a null List<string> object to the PopulateList() method: 

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAMethod_WhenNullArgumentsPassed_VerifyThrowsNullReferenceException()
{
    var namesObj = new ExceptionMethods();

    List<string> currentPeople = null;
    var peopleList = namesObj.PopulateList(currentPeople);

    Assert.IsNull(peopleList);
}

Assuming that a method is going to always get non-null arguments is why we get the exception in this case. Therefore, just like in our other examples, we need to check for null arguments before appending items to the list. Besides that, we can use different exception handling techniques to deal with the exception as we invoke the PopulateList() method as we can see in this example:

public List<string> FixedPopulateList(List<string> peopleNames)
{
    var names = new string[] { "John", "Mary", "Andrew", "Grace", "Aston", "Sheila" };

    if (peopleNames == null) 
    {
        peopleNames = new List<string>();
    }

    foreach (var person in names) 
    {
        peopleNames.Add(person);
    }
        
    return peopleNames;
}

Here, we see that we check whether the list is null before attempting to append a list of names to it, which helps us avoid the NullReferenceException error. We can proceed to verify that the FixedPopulateList() method returns a List<string> object that is not null:

var namesObj = new ExceptionMethods();

List<string> currentPeople = null;
var peopleList = namesObj.FixedPopulateList(currentPeople);

Assert.IsNotNull(peopleList);
CollectionAssert.Contains(peopleList, "Mary");

How to Debug the NullReferenceException in C#?

There are different ways that we can use to find the source of a NullReferenceException in C#.

Generally, when using Visual Studio, we can use different debugging strategies to anticipate and fix syntax and logical errors. Although the compiler may show some warnings and show where the error is, one of the most common techniques that we can use is setting breakpoints strategically to anticipate any errors. 

We can also use unit tests to verify that such exceptions don’t occur before shipping out code to production. Finally, we can inspect variables and all their references to ensure that they have non-null references to avoid getting the NullReferenceException. 

How to Avoid Getting the NullReferenceExpection in C#?

To start with, we can avoid getting the NullReferenceException in C# by always checking for null values and ignoring them or replacing them with default values as we have done in our last example:

if (result != null)
{
    return result.ToString();
}
else
{
    return $"{searchString} could not be found";
}

Besides checking for null values, we can use exception handling techniques to ensure that our code does not trigger such exceptions during execution. Simple try-catch blocks or the use of custom exceptions can come in handy when debugging applications as they can help us isolate problematic code. 

On top of that, C# supports nullable types, which we can use in these situations. For example, we can define a nullable integer as int? number = null; which is the shortened version of  Nullable<int> number = null;. In this case, the question mark shows that the variable can hold  null in the variable number. We can then proceed to check whether number is null with if statements such as if (number.HasValue) or if (number == null)

To avoid getting the NullReferenceException at the project level, we can take advantage of nullable contexts. These contexts help us control how the compiler interprets reference types. To protect the project against the NullReferenceExecption, we can choose to enable it in the project’s csproj file as <Nullable>enable<Nullable>. To understand all the different options that we can use with nullable contexts, please refer to this article. 

Using the Null-Coalescing Operator

Finally, we can use the null-coalescing operator ?? as a way to avoid getting the NullReferenceException in C#. The null-coalescing operator is a binary operator that is used to assign a default value to a variable. The left-hand operand must be of a reference type, and the right-hand operand must be of the same type or convertible to the type of the left-hand operand. If the left-hand operand is not null, it is evaluated and returned; otherwise, the right-hand operand is evaluated and becomes the result of the operation.

Here is an example of how we can use the null-coalescing operator in C#:

int? num = null;
int result = num ?? 0; 

First, we assign the value null to the num variable. Next, we proceed to check if the value of num is not null, then result will be equal to num. On the other hand, if num is null, then result will be equal to 0. By using this operator, we can assign a default value to a variable if the variable is null, which helps us avoid a NullReferenceException.

These are useful ways to prevent errors in our code and make our code more robust.

Conclusion

In this article, we have learned the causes of NullReferenceException, debugging techniques, and how to avoid getting it as we code. We are eager to keep learning together, so, in case you think of some scenarios that can cause the NullReferenceExecption that are not in this article, please free to comment below and we’ll add them as soon as possible. 

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

C# NullReferenceException

Introduction of C# NullReferenceException

The NullReferenceException is an exception that is thrown by the program when we attempt to access any type of member which has value as null, meaning when we try to access a variable that holds no value or a null value, Null Reference exception will be thrown. This exception is applied for various releases of .NET, .NET Core, and .Net Framework. These reference variables in C# are quite matching with the concepts pf pointers in C. There are various situations when the NullReferenceException occurs and there are multiple ways to avoid or solve it.

Syntax:

Follow is the standard syntax used for the implementation of the NullReferenceException:

public class NullReferenceException :SystemException

The Null Reference Exception is inherited from System Exceptions which basically can be found within Object and into Exception. As we know this is one of the most common exception and there are various ways to handle it.

How NullReferenceException Works in C#?

To simply understand, a Null Reference Exception is a result of an event where we try to access a variable that is not referencing any other object. Now, referring to a reference isn’t a problem here, but when a reference variable is not referencing any other object, then it is basically treated as null. This is where the problem arises when the code is referenced to a point which ends up into a null, then we are encountered with an exception, named NullReferenceException. There can be various scenarios where a Null Reference Exception is thrown by the program. When we execute a program and if it encounters the null reference exception, the output will be something like this:

Unhandled Exception:
System.NullReferenceException: Object reference not set to the instance of the object.

Examples

Now that we have understood what the exception is about and how it works, let us move to properly demonstrating the exception with examples. For our first example, which is very simple, we have a simple variable that holds null value and then we will attempt to work do that variable, but being a null, it will throw the Null Reference Exception. The code for the program is as follows:

Code:

using System;
public class SampleProgram {
public static void Main()     {
string name = null;
varval =name.ToString();
Console.WriteLine(val);
}
}

Code Explanation: Stated with using System, we have our class Sample which is public. Then we have our static void main statement, followed by the creation of a simple string variable named name and value assigned is null, meaning no value to the variable. This string variable is important here, later we create another variable named val, where we attempt to convert the value of name into a string. Finally, we have out a print statement that will print the value of name, which is now converted using ToString(). Refer the below attached screenshot for output:

Output:

C# NullReferenceException-1.1

If executed properly, the code will throw an error, which will be NullReferenceException. And the reason will be that when we are trying to call the ToString() method, it will go to the variable name, but our variable name has no value, meaning null. And as we know, the null value can’t be converted using ToString(). So our code will only print an error, which means code is running as expected.

As explained the program has been terminated by an exception. Moving on, we will demonstrate another simple example, which as explained lead to the same exception.

Code:

using System;
class SampleProgram {
static void Main() {
string val = null;
if (val.Length == 0) {
Console.WriteLine(val);
}
}
}

Code Explanation: Similar to our first example, here we have our namespace and first call, which holds the main statement. Then we have our string variable with value as null. This will be the major variable, which will lead to our expected exception. Then we have a simple if condition where we will check if the length of our variable is zero or not and if it is zero it will move to the next step and print the value. But the code will not move to the final print line as it will encounter an exception while within the if. Refer the below attached screenshot for output:

Output:

Output-1.2

Here, the output is just as our first example, “Unhandled Exception” because the exception is the same, we tried to implement a function here but as explained our variable has a null value which leads us to Null Reference Exception. Now that we have seen and understood how and why this null reference exception occurs, it is important to understand how we can avoid it for better functioning of the program.

How to Avoid NullReferenceException in C#?

The Null Reference Exception is not a major error, but one of the common ones and one of the basic and simple way to avoid the Null Reference Exception is to check the variable or property before moving ahead and accessing it. And a very basic way to do this is to check the variable within an if statement. We will demonstrate an example where we will avoid the occurrence of the exception and the code will move on.

Code:

using System;
class SampleProgram {
static void Main() {
string val = null;
if (val == null) {
Console.WriteLine("n Value to the variable is null.");
}
else{
Console.WriteLine(val);
}
}
}

Output:

0utput-1.3

Code Explanation: Here we have our class which holds the main statement than a variable with a null value. Then we enter an if else statement, where the value of the variable is checked if it is null, the print statement will be printed and the program will terminate, if the value is not null, then it will move ahead and into else part, it will print the value. As expected our code printed that “Value to the variable is null.” because the value is null. If we try the same example with a string value, the program will proceed and the else part will be printed.

Conclusion

The NullReferenceException is encountered when we attempt to access a variable which holds a null value, it can be variable or object. The reference should not hold null value else the exception will be thrown. There are many situations where this can be seen and the simplest way to avoid the NullReferenceException is to check beforehand, before accessing the value.

Recommended Articles

This is a guide to C# NullReferenceException. Here we also discuss the introduction and how nullreferenceexception works in c# along with examples and its code implementation. You may also have a look at the following articles to learn more –

  1. C# Anonymous Functions
  2. C# SortedSet
  3. C# finally
  4. C# SortedList

A NullReferenceException happens when you try to access a reference variable that isn’t referencing any object. If a reference variable isn’t referencing an object, then it’ll be treated as null. The run-time will tell you that you are trying to access an object, when the variable is null by issuing a NullReferenceException.

Reference variables in c# and JavaScript are similar in concept to pointers in C and C++. Reference types default to null to indicate that they are not referencing any object. Hence, if you try and access the object that is being referenced and there isn’t one, you will get a NullReferenceException.

When you get a NullReferenceException in your code it means that you have forgotten to set a variable before using it. The error message will look something like:

NullReferenceException: Object reference not set to an instance of an object
  at Example.Start () [0x0000b] in /Unity/projects/nre/Assets/Example.cs:10 

This error message says that a NullReferenceException happened on line 10 of the script file Example.cs. Also, the message says that the exception happened inside the Start() function. This makes the Null Reference Exception easy to find and fix. In this example, the code is:

//c# example
using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    // Use this for initialization
    void Start () {
        __GameObject__The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject's functionality is defined by the Components attached to it. [More info](class-GameObject.html)<span class="tooltipGlossaryLink">See in [Glossary](Glossary.html#GameObject)</span> go = GameObject.Find("wibble");
        Debug.Log(go.name);
    }

}

The code simply looks for a game object called “wibble”. In this example there is no game object with that name, so the Find() function returns null. On the next line (line 9) we use the go variable and try and print out the name of the game object it references. Because we are accessing a game object that doesn’t exist the run-time gives us a NullReferenceException

Null Checks

Although it can be frustrating when this happens it just means the script needs to be more careful. The solution in this simple example is to change the code like this:

using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    void Start () {
        GameObject go = GameObject.Find("wibble");
        if (go) {
            Debug.Log(go.name);
        } else {
            Debug.Log("No game object called wibble found");
        }
    }

}

Now, before we try and do anything with the go variable, we check to see that it is not null. If it is null, then we display a message.

Try/Catch Blocks

Another cause for NullReferenceException is to use a variable that should be initialised in the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary
. If you forget to do this, then the variable will be null. A different way to deal with NullReferenceException is to use try/catch block. For example, this code:

using UnityEngine;
using System;
using System.Collections;

public class Example2 : MonoBehaviour {

    public Light myLight; // set in the inspector

    void Start () {
        try {
            myLight.color = Color.yellow;
        }       
        catch (NullReferenceException ex) {
            Debug.Log("myLight was not set in the inspector");
        }
    }

}

In this code example, the variable called myLight is a Light which should be set in the Inspector window. If this variable is not set, then it will default to null. Attempting to change the color of the light in the try block causes a NullReferenceException which is picked up by the catch block. The catch block displays a message which might be more helpful to artists and game designers, and reminds them to set the light in the inspector.

Summary

  • NullReferenceException happens when your script code tries to use a variable which isn’t set (referencing) and object.
  • The error message that appears tells you a great deal about where in the code the problem happens.
  • NullReferenceException can be avoided by writing code that checks for null before accessing an object, or uses try/catch blocks.

In this article,we will learn: what is NullReferenceException and How to avoid it?

Null Reference Exception

  NullReferenceException or ‘Object Reference not set to an Instance of an Object’ is a very common exception. That indicates, you are trying to access member fields, or function types, on an object reference that points to null. This means the reference is null, and you cannot access members through a null reference.

Example:

using System;

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

Output:

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at Program.Main() in C:Users…
 

Common Scenarios:

1. Array:

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

2. Array Elements:

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

3. Jagged Arrays:

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.

4. Collection/List/Dictionary:

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

5. Range Variable (Indirect/Deferred):

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.

6. Events:

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

7. Incorrect use of 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

Different ways to avoid NullReferenceException?

1. Explicitly check for Null and ignore Null Values:

If you expect the reference sometimes to be null, you can check for it being null before accessing instance members.

void PrintAge(Employee emp) {
    if (emp != null) {
        Console.WriteLine(emp.Age);
    }
}

2. Explicitly check for Null and provide a default Value:

If you expect the reference sometimes to be null, you can check for it being null before accessing instance members and return a default value.

string GetName(Employee emp) {
    if (emp == null)
        return "Unknown";
    return emp.Name;
}

3. Explicitly check for Null and throw a Custom Exception:

string GetName(Employee emp) {
    if (emp == null)
        throw new EmployeeNotFoundException(emp);  
        return emp.Name;
}

4. Use GetValueOrDefault() for nullable value types to provide a default value when they are 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

5. Use the null coalescing operator: ??

The null coalescing operator “??” uses two question marks. With it you can use a custom value for a null reference variable.

class Program
{
    static string _name;
    static string Name
    {
  get
  {
      return _name ?? "Default";
  }
  set
  {
      _name = value;
  }
    }

    static void Main()
    {
  Console.WriteLine(Name);
  Name = "csharp";
  Console.WriteLine(Name);
  Name = null;
  Console.WriteLine(Name);
    }
}

6. Use the null conditional operator: ?.

Similar to the coalescing operator, the null conditional operator tests for null before accessing a member of an instance.

 class Program
    {
        static void Main(string[] args)
        {
            Employee Emp = new Employee();
            if (Emp.Name == String.Empty)
            {
                Emp = null;
            }
 
            WriteLine(Emp?.Name ?? "Field is null.");
 
            ReadLine();
        }
    }
 
    public class Employee
    {
        public string Name { get; set; } = "";
    }

7. Using Extension Method:

you can Combine NotNull with an extension method as below example.

[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;
    }
}
//how to use it?
var person = GetPerson().NotNull();

  Thanks for visiting !!

© 2016, Csharp Star. All rights reserved.

The “Object reference not set to an instance of an object” is a very famous error in C# that appears when you get a NullReferenceException. This occurs when you try to access a property or method of an object that points to a null value. They can be fixed using Null conditional operators and handled using try-catch blocks.

In this post, we will learn more about the error and the ways to fix it.

What is “NullReferenceException: Object reference not set to an instance of an object” error?

As mentioned earlier, the NullReferenceException indicates that your code is trying to work with an object that has a null value as its reference. This means that the reference object has not been initialized.

This is a runtime exception that can be caught using a try-catch block.

Example code

try
{
    string a = null;
    a.ToString();
}
catch (NullReferenceException e)
{
    //Code to do something with e
}

How to fix this error?

You can fix this error by using the following methods:

  • Using Null conditional operators
  • Using the Null Coalescing operator
  • Using nullable datatypes in C#   

1) Using Null conditional operators

This method is easier than using an if-else condition to check whether the variable value is null. Look at this example,

int? length = customers?.Length; // this will return null if customers is null, instead of throwing the exception

2) Using the Null Coalescing operator

This operator looks like “??” and provides a default value to variables that have a null value. It is compatible with all nullable datatypes.

Example

int length = customers?.Length ?? 0; // 0 is provided by default if customers is null      

3) Using nullable datatypes in C#   

All reference types in C# can have a null value. But some data types such as int and Boolean cannot take null values unless they are explicitly defined. This is done by using Nullable data types.

For example,

static int Add(string roll_numbers)
{
return roll_numbers.Split(","); // This code might throw a NullReferenceException as roll_numbers variable can be null 
}

Correct code

static int Add(string? roll_numbers) // As roll_numbers argument can now be null, the NullReferenceException can be avoided  
{
return roll_numbers.Split(",");  
}

The best way to avoid the «NullReferenceException: Object reference not set to an instance of an object” error is to check the values of all variables while coding. You can also use a simple if-else statement to check for null values, such as if (numbers!=null) to avoid this exception.

In C#, a NullReferenceException occurs when we try to access a variable whose value has not been set or has been set to null. It can be easy to trigger this exception accidentally, so it’s important to be aware of how to avoid it in the first place. In this article, we’ll take a look at some common causes of NullReferenceException errors and how to fix them. We’ll also discuss ways to prevent NullReferenceException errors from happening in the first place.

To download the source code for this article, you can visit our GitHub repository.

Without further ado, let’s get started!

What Is a Null Object in C#?

In C#, a null object is an uninitialized object. This means that the object doesn’t have a value (other than null) assigned to it yet. When we create a new object, it’s automatically assigned a null value. We can change this by explicitly assigning a value to the object, but it will remain null until we do so.

Let’s understand what causes the NullReferenceException in C#. 

As the name suggests, the NullReferenceException in C# occurs when we try accessing a null object.

Just like other object references, we can pass null values when we attempt to dereference them or pass them to other methods, which can make it difficult to debug and fix this exception. 

We can get the NullReferenceException thrown in various scenarios, which we’ll now look at.

Forgetting to Instantiate a Reference Type

Forgetting to instantiate a reference type is one of the most common causes of this exception:

public List<string> StudentList() 
{
    List<string> studentList = null;

    studentList.Add("John Doe");

    return studentList;
}

Here, we intend to return a List<string> containing a value “John Doe” to the user but the compiler throws a NullReferenceException when we attempt to run it. 

Next, we can verify that the compiler throws the NullReferenceException successfully:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAListObject_WhenNotInstantiated_VerifyThrowsNullReferenceException()
{
    var studentObj = new ExceptionMethods();

    var studentList = studentObj.StudentList();

    Assert.IsNull(studentList);
}

To fix that error, we simply need to instantiate the studentList object in the right way:

public List<string> FixedStudentList()
{
    var studentList = new List<string>();

    studentList.Add("John Doe");

    return studentList;
}

We can proceed to verify that the FixedStudentList() method works correctly by checking that it returns “John Doe” and is not null:

var studentObj = new ExceptionMethods();

var studentList = studentObj.FixedStudentList();
var student = "John Doe";

Assert.IsNotNull(studentList);
Assert.IsInstanceOfType(studentList, typeof(List<string>));
CollectionAssert.Contains(studentList, student);

Failing to Dimension Arrays Before Initializing Them

We have to dimension arrays before initializing them. Therefore, when we attempt to declare an array without specifying the number of elements it is going to hold, it will result in a NullReferenceException being thrown when we attempt to initialize its values.

Let’s simulate this scenario with an example:

public int[] RandomNumbers()
{
    var rand = new Random();

    int[] numbers = null;

    for (int i = 0; i < numbers.Length; i++) 
    {
        numbers[i] = rand.Next();
    }
 
    return numbers;
}

Here, we try to generate random numbers but we do not specify the number of elements while declaring the array, which throws the NullRefereceException:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenNotInstantiated_VerifyThrowsNullReferenceException()
{
    var arrayObj = new ExceptionMethods();

    var randomNumbers = arrayObj.RandomNumbers();

    Assert.IsNull(randomNumbers);
}

To fix this error, we need to declare the number of elements before initializing the array:

public int[] FixedRandomNumbers()
{
    var rand = new Random();

    var numbers = new int[50];

    for (int i = 0; i < numbers.Length; i++)
    {
        numbers[i] = rand.Next();
    }

    return numbers;
}

Next, we can also go ahead to verify that the method runs successfully without any errors:

var arrayObj = new ExceptionMethods();

var randomNumbers = arrayObj.FixedRandomNumbers();

Assert.IsNotNull(randomNumbers);
Assert.IsInstanceOfType(randomNumbers, typeof(int[]));          

Assuming a Method Always Returns Non-null Values

As the title suggests, sometimes we may erroneously assume that a method is going to return non-null values. For example, a database table may contain some null values, which we have to account for when implementing our business logic.

Let’s implement a simple class to simulate this scenario:

public class Teacher
{
    public string? FirstName { get; set; }

    public Teacher()
    {
    }

    public Teacher[] AddRange(string[] firstNames)
    {
        var teachers = new Teacher[firstNames.Length];

        for (int i = 0; i < firstNames.Length; i++) 
        {
            teachers[i] = new Teacher(firstNames[i]);
        }
            
        return teachers;
    }

    public Teacher(string firstName)
    {
        this.FirstName = firstName;
    }
}

First, we define a property FirstName that must always have a non-null value when exiting the constructor. The AddRange method takes a string array and returns an object of the type Teacher[]

Next, we are going to implement a simple method to search for a single teacher from the Teacher[] array:

public string Teachers(string searchString)
{
    var personObj = new Teacher();
    
    var people = personObj.AddRange(new string[] { "John", "Mary", "Jane", "Usher", "Andrew", "Grace", "Aston", "Sheila" });
    var result = Array.Find(people, p => p.FirstName == searchString);

    return result.ToString();
}

The Teachers() method takes a string searchString as its sole parameter and uses the inbuilt Array.Find() method to search for it. Since FirstName is a non-nullable property, we are assuming that the method will always return a value.

We can verify that the Teachers method throws a NullReferenceException with this test:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenSearching_VerifyThrowsNullReferenceException()
{
    var listObj = new ExceptionMethods();

    var searchPerson = listObj.Teachers("Steve");

    Assert.IsNull(searchPerson);
}

To address this problem, we need to ensure that we check for the method’s return value to make sure it is not null:

public string FixedTeachers(string searchString)
{
    var personObj = new Teacher();

    var people = personObj.AddRange(new string[] { "John", "Mary", "Jane", "Usher", "Andrew", "Grace", "Aston", "Sheila" });
    var result = Array.Find(people, p => p.FirstName == searchString);
    if (result != null)
    {
        return result.ToString();
    }
    else
    {
        return $"{searchString} could not be found";
    }
}

We can verify that our fix works by checking whether the FixedTeachers() method returns a string and is not null: 

var listObj = new ExceptionMethods();

var searchPerson = listObj.FixedTeachers("Steve");

Assert.IsNotNull(searchPerson);
Assert.IsInstanceOfType(searchPerson, typeof(string));

Enumerating Arrays Elements With Reference Types

In some cases, we may encounter the NullReferenceException when attempting to process array elements when some of them are null. Let’s try to simulate this scenario with an example:

public string[] CapitalizeNames() 
{
    var names = new string[] { "John", "Mary", null, null, "Andrew", "Grace", "Aston", "Sheila" };

    for (int i = 0; i < names.Length; i++)
    {
        names[i] = names[i].ToUpper();
    }

    return names;
}

The CapitalizeNames() method converts the string elements in the names array to upper-case using the inbuilt string.ToUpper() method. However, since some of the elements are null, attempting to convert them to uppercase throws the NullReferenceException, which we can verify:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAnArray_WhenSomeElementsNull_VerifyThrowsNullReferenceException()
{
    var arrayObj = new ExceptionMethods();
    
    var capitalizedNames = arrayObj.CapitalizeNames();
    
    Assert.IsNull(capitalizedNames);
}

To resolve this error, we need to check for null values before calling the string.ToUpper() method. We can make use of the string.Length property or the string.IsNullOrEmpty() method to check if a given array element is null:

public string[] FixedCapitalizeNames()
{
    var names = new string[] { "John", "Mary", null, null, "Andrew", "Grace", "Aston", "Sheila" };

    for(int i = 0; i < names.Length; i++)
    {
        if (!string.IsNullOrEmpty(names[i])) 
        {
            names[i] = names[i].ToUpper();
        }
    }

    return names;
}

We can then proceed to check that our method works without any issues with this test:

var arrayObj = new ExceptionMethods();

var capitalizedNames = arrayObj.FixedCapitalizeNames();

Assert.IsNotNull(capitalizedNames);
CollectionAssert.Contains(capitalizedNames, "JOHN");

Passing Null Arguments to Methods

We can trigger the exception when we attempt to pass null arguments to methods. Just like other reference types, we can pass null objects across different methods. Some methods may validate the arguments they receive and end up throwing the System.ArgumentNullException when they detect null arguments. On the other hand, when the methods fail to check for null arguments they end up throwing the NullReferenceException instead. 

Let’s simulate this scenario with an example:

public List<string> PopulateList(List<string> peopleNames) 
{
    var names = new string[] { "John", "Mary", "Andrew", "Grace", "Aston", "Sheila" };

    foreach (var person in names) 
    {
        peopleNames.Add(person);
    }
        
    return peopleNames;
}

The PopulateList() method takes a peopleNames list object and appends the array of elements in the names array to that list before returning it back to the user. Here, we are assuming that the PeopleList() method is going to always receive arguments that are not null. 

Let’s test what happens when we try to pass a null List<string> object to the PopulateList() method: 

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GivenAMethod_WhenNullArgumentsPassed_VerifyThrowsNullReferenceException()
{
    var namesObj = new ExceptionMethods();

    List<string> currentPeople = null;
    var peopleList = namesObj.PopulateList(currentPeople);

    Assert.IsNull(peopleList);
}

Assuming that a method is going to always get non-null arguments is why we get the exception in this case. Therefore, just like in our other examples, we need to check for null arguments before appending items to the list. Besides that, we can use different exception handling techniques to deal with the exception as we invoke the PopulateList() method as we can see in this example:

public List<string> FixedPopulateList(List<string> peopleNames)
{
    var names = new string[] { "John", "Mary", "Andrew", "Grace", "Aston", "Sheila" };

    if (peopleNames == null) 
    {
        peopleNames = new List<string>();
    }

    foreach (var person in names) 
    {
        peopleNames.Add(person);
    }
        
    return peopleNames;
}

Here, we see that we check whether the list is null before attempting to append a list of names to it, which helps us avoid the NullReferenceException error. We can proceed to verify that the FixedPopulateList() method returns a List<string> object that is not null:

var namesObj = new ExceptionMethods();

List<string> currentPeople = null;
var peopleList = namesObj.FixedPopulateList(currentPeople);

Assert.IsNotNull(peopleList);
CollectionAssert.Contains(peopleList, "Mary");

How to Debug the NullReferenceException in C#?

There are different ways that we can use to find the source of a NullReferenceException in C#.

Generally, when using Visual Studio, we can use different debugging strategies to anticipate and fix syntax and logical errors. Although the compiler may show some warnings and show where the error is, one of the most common techniques that we can use is setting breakpoints strategically to anticipate any errors. 

We can also use unit tests to verify that such exceptions don’t occur before shipping out code to production. Finally, we can inspect variables and all their references to ensure that they have non-null references to avoid getting the NullReferenceException. 

How to Avoid Getting the NullReferenceExpection in C#?

To start with, we can avoid getting the NullReferenceException in C# by always checking for null values and ignoring them or replacing them with default values as we have done in our last example:

if (result != null)
{
    return result.ToString();
}
else
{
    return $"{searchString} could not be found";
}

Besides checking for null values, we can use exception handling techniques to ensure that our code does not trigger such exceptions during execution. Simple try-catch blocks or the use of custom exceptions can come in handy when debugging applications as they can help us isolate problematic code. 

On top of that, C# supports nullable types, which we can use in these situations. For example, we can define a nullable integer as int? number = null; which is the shortened version of  Nullable<int> number = null;. In this case, the question mark shows that the variable can hold  null in the variable number. We can then proceed to check whether number is null with if statements such as if (number.HasValue) or if (number == null)

To avoid getting the NullReferenceException at the project level, we can take advantage of nullable contexts. These contexts help us control how the compiler interprets reference types. To protect the project against the NullReferenceExecption, we can choose to enable it in the project’s csproj file as <Nullable>enable<Nullable>. To understand all the different options that we can use with nullable contexts, please refer to this article. 

Using the Null-Coalescing Operator

Finally, we can use the null-coalescing operator ?? as a way to avoid getting the NullReferenceException in C#. The null-coalescing operator is a binary operator that is used to assign a default value to a variable. The left-hand operand must be of a reference type, and the right-hand operand must be of the same type or convertible to the type of the left-hand operand. If the left-hand operand is not null, it is evaluated and returned; otherwise, the right-hand operand is evaluated and becomes the result of the operation.

Here is an example of how we can use the null-coalescing operator in C#:

int? num = null;
int result = num ?? 0; 

First, we assign the value null to the num variable. Next, we proceed to check if the value of num is not null, then result will be equal to num. On the other hand, if num is null, then result will be equal to 0. By using this operator, we can assign a default value to a variable if the variable is null, which helps us avoid a NullReferenceException.

These are useful ways to prevent errors in our code and make our code more robust.

Conclusion

In this article, we have learned the causes of NullReferenceException, debugging techniques, and how to avoid getting it as we code. We are eager to keep learning together, so, in case you think of some scenarios that can cause the NullReferenceExecption that are not in this article, please free to comment below and we’ll add them as soon as possible. 

Понравилась статья? Поделить с друзьями:
  • Ошибка no such file or directory означает что
  • Ошибка null pointer exception
  • Ошибка no such file or directory linux
  • Ошибка null iphone
  • Ошибка no such device grub