Ошибка nullreferenceexception object reference not set to an instance of an object

Причина

Вкратце

Вы пытаетесь воспользоваться чем-то, что равно 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;

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.

NullReferenceException возникает, когда вы пытаетесь получить доступ к ссылочной переменной, которая не ссылается на какой-либо объект. Если ссылочная переменная не ссылается на объект, она будет рассматриваться как null. Время выполнения сообщит вам, что вы пытаетесь получить доступ к объекту, когда переменная имеет значение null, создав исключение NullReferenceException.

Ссылочные переменные в C# и JavaScript по своей концепции аналогичны указателям в C и C++. Типы ссылок по умолчанию имеют значение null, чтобы указать, что они не ссылаются на какой-либо объект. Следовательно, если вы попытаетесь получить доступ к объекту, на который ссылаются, а его нет, вы получите NullReferenceException.

Когда вы получаете NullReferenceException в своем коде, это означает, что вы забыли установить переменную перед ее использованием. Сообщение об ошибке будет выглядеть примерно так:

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

В этом сообщении об ошибке говорится, что NullReferenceException произошло в строке 10 файла сценария Example.cs. Кроме того, в сообщении говорится, что исключение произошло внутри функции Start(). Это упрощает поиск и исправление исключения нулевой ссылки. В этом примере код такой:

//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)See in [Glossary](Glossary#GameObject) go = GameObject.Find("wibble");
Debug.Log(go.name);
}

}

Код просто ищет игровой объект под названием «wibble». В этом примере нет игрового объекта с таким именем, поэтому функция Find() возвращает null. В следующей строке (строка 9) мы используем переменную go и пытаемся вывести имя игрового объекта, на который она ссылается. Поскольку мы обращаемся к несуществующему игровому объекту, среда выполнения выдает нам NullReferenceException

Нулевые проверки

Хотя это может расстраивать, когда это происходит, это просто означает, что сценарий должен быть более осторожным. Решение в этом простом примере состоит в том, чтобы изменить код следующим образом:

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

}

Теперь, прежде чем пытаться что-то делать с переменной go, мы проверяем, не является ли она null. Если это null, мы показываем сообщение.

Попробовать/перехватить блоки

Другой причиной NullReferenceException является использование переменной, которая должна быть инициализирована в ИнспектореОкно Unity, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет просматривать и редактировать значения. Дополнительная информация
См. в Словарь
. Если вы забудете это сделать, переменная будет иметь значение null. Другой способ справиться с NullReferenceException — использовать блок try/catch. Например, этот код:

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

}

В этом примере кода переменная с именем myLight — это Light, которую следует установить в окне инспектора. Если эта переменная не задана, по умолчанию она будет иметь значение null. Попытка изменить цвет света в блоке try вызывает NullReferenceException, которое подхватывается блоком catch. Блок catch отображает сообщение, которое может быть более полезным для художников и геймдизайнеров, и напоминает им о необходимости установить свет в инспекторе.

Обзор

  • NullReferenceException возникает, когда ваш код скрипта пытается использовать переменную, которая не установлена ​​(ссылка) и объект.
  • Отображаемое сообщение об ошибке многое говорит о том, в каком месте кода возникает проблема.
  • NullReferenceException можно избежать, написав код, который проверяет null перед доступом к объекту или использует блоки try/catch.

вот вы описали класс:

public class Tours
    {
        public List<TourInfo> tourInfos { get; set; }
    }

вот вы создали экземпляр класса в методе роута:
Tours tours = new Tours();

заметьте, конструктор отработал, но поле tourInfos так и осталось не инициализированным
затем вы пытаетесь обратиться к не инициализированному полю объекта

tours.tourInfos[0].beachType = "one";// здесь возникает ошибка | И правильно, потому что tours.tourInfos - null
            tours.tourInfos[1].beachType = "two";

и получаете вполне закономерную ругань платформы на «обращение по несуществующей ссылке».
Вам нужно инициализировать в конструкторе Tours, поле tourInfos (new List()).
Но на этом ваша история не закончится, т.к. на строчках

tours.tourInfos[0].beachType = "one";// здесь возникает ошибка
            tours.tourInfos[1].beachType = "two";

система вам опять выбросит то же самое исключение, потому что у вас в коллекции tourInfos не существует ни одного экземпляра класса TourInfo, к которому вы пытаетесь обратится по индексу и изменить у него какое-то свойство. Сначала создайте эти объекты, затем добавьте их в лист, а уж потом доставайте их из листа по индексу и заполняйте необходимые свойства(ну или сначала создайте объекты, задайте им свойства, а потом добавляйте в лист).

По идеи должна вернутся строка с двумя JSON массивами, где все кроме beachType будет null.

нет, судя по вашему коду вам вернётся один JSON массив с двумя объектами в нём.

Value type vs Reference type

In many programming languages, variables have what is called a «data type». The two primary data types are value types (int, float, bool, char, struct, …) and reference type (instance of classes). While value types contains the value itself, references contains a memory address pointing to a portion of memory allocated to contain a set of values (similar to C/C++).

For example, Vector3 is a value type (a struct containing the coordinates and some functions) while components attached to your GameObject (including your custom scripts inheriting from MonoBehaviour) are reference type.

When can I have a NullReferenceException?

NullReferenceException are thrown when you try to access a reference variable that isn’t referencing any object, hence it is null (memory address is pointing to 0).

Some common places a NullReferenceException will be raised:

Manipulating a GameObject / Component that has not been specified in the inspector

// t is a reference to a Transform.
public Transform t ;

private void Awake()
{
     // If you do not assign something to t
     // (either from the Inspector or using GetComponent), t is null!
     t.Translate();
}

Retrieving a component that isn’t attached to the GameObject and then, trying to manipulate it:

private void Awake ()
{
    // Here, you try to get the Collider component attached to your gameobject
    Collider collider = gameObject.GetComponent<Collider>();

    // But, if you haven't any collider attached to your gameobject,
    // GetComponent won't find it and will return null, and you will get the exception.
    collider.enabled = false ;
}

Accessing a GameObject that doesn’t exist:

private void Start()
{
    // Here, you try to get a gameobject in your scene
    GameObject myGameObject = GameObject.Find("AGameObjectThatDoesntExist");

    // If no object with the EXACT name "AGameObjectThatDoesntExist" exist in your scene,
    // GameObject.Find will return null, and you will get the exception.
    myGameObject.name = "NullReferenceException";
}

Note: Be carefull, GameObject.Find, GameObject.FindWithTag, GameObject.FindObjectOfType only return gameObjects that are enabled in the hierarchy when the function is called.

Trying to use the result of a getter that’s returning null:

var fov = Camera.main.fieldOfView;
// main is null if no enabled cameras in the scene have the "MainCamera" tag.

var selection = EventSystem.current.firstSelectedGameObject;
// current is null if there's no active EventSystem in the scene.

var target = RenderTexture.active.width;
// active is null if the game is currently rendering straight to the window, not to a texture.

Accessing an element of a non-initialized array

private GameObject[] myObjects ; // Uninitialized array

private void Start()
{
    for( int i = 0 ; i < myObjects.Length ; ++i )
        Debug.Log( myObjects[i].name ) ;
}

Less common, but annoying if you don’t know it about C# delegates:

delegate double MathAction(double num);

// Regular method that matches signature:
static double Double(double input)
{
    return input * 2;
}

private void Awake()
{
    MathAction ma ;

    // Because you haven't "assigned" any method to the delegate,
    // you will have a NullReferenceException
    ma(1) ;

    ma = Double ;

    // Here, the delegate "contains" the Double method and
    // won't throw an exception
    ma(1) ;
}

How to fix ?

If you have understood the previous paragraphes, you know how to fix the error: make sure your variable is referencing (pointing to) an instance of a class (or containing at least one function for delegates).

Easier said than done? Yes, indeed. Here are some tips to avoid and identify the problem.

The «dirty» way : The try & catch method :

Collider collider = gameObject.GetComponent<Collider>();

try
{
    collider.enabled = false ;
}       
catch (System.NullReferenceException exception) {
    Debug.LogError("Oops, there is no collider attached", this) ;
}

The «cleaner» way (IMHO) : The check

Collider collider = gameObject.GetComponent<Collider>();

if(collider != null)
{
    // You can safely manipulate the collider here
    collider.enabled = false;
}    
else
{
    Debug.LogError("Oops, there is no collider attached", this) ;
}

When facing an error you can’t solve, it’s always a good idea to find the cause of the problem. If you are «lazy» (or if the problem can be solved easily), use Debug.Log to show on the console information which will help you identify what could cause the problem. A more complex way is to use the Breakpoints and the Debugger of your IDE.

Using Debug.Log is quite useful to determine which function is called first for example. Especially if you have a function responsible for initializing fields. But don’t forget to remove those Debug.Log to avoid cluttering your console (and for performance reasons).

Another advice, don’t hesitate to «cut» your function calls and add Debug.Log to make some checks.

Instead of :

 GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;

Do this to check if every references are set :

GameObject myObject = GameObject.Find("MyObject") ;

Debug.Log( myObject ) ;

MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;

Debug.Log( superComponent ) ;

superComponent.value = "foo" ;

Even better :

GameObject myObject = GameObject.Find("MyObject") ;

if( myObject != null )
{
   MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
   if( superComponent != null )
   {
       superComponent.value = "foo" ;
   }
   else
   {
        Debug.Log("No SuperComponent found onMyObject!");
   }
}
else
{
   Debug.Log("Can't find MyObject!", this ) ;
}

Sources:

  1. http://answers.unity3d.com/questions/47830/what-is-a-null-reference-exception-in-unity.html
  2. https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it/218510#218510
  3. https://support.unity3d.com/hc/en-us/articles/206369473-NullReferenceException
  4. https://unity3d.com/fr/learn/tutorials/topics/scripting/data-types

  • Ошибка null при обновлении iphone 6s что означает
  • Ошибка null при обновлении ipad
  • Ошибка null при загрузке файла
  • Ошибка null при входе на сервер майнкрафт
  • Ошибка null при входе на сервер hypixel