Причина
Вкратце
Вы пытаетесь воспользоваться чем-то, что равно 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;
-
- #1
I’ve run into an issue recently with SP-Tarkov that’s left me unable to play the game. I recently finished a raid on Customs, but after that, I started getting the error message, «Object reference not set to an instance of an object.» I have no clue what it means, or if it’s referencing a conflict in a mod or not. All I do know is it happened after a raid in Customs, and so far, the only thing I can deduce is it has to do with a thermal optic conflicting somewhere. Can someone help me out with finding out what is happening here?
-
- #2
The same thing just happened to me under the same circumstances except I didn’t have and thermals on me or mods installed
-
- #3
Based on your client logs it seems like either some files are missing from the mod ClearVision, or there is another mod conflicting with the bundles that ClearVision edits.
I would start by reinstalling CV to see if that fixes it. If that doesn’t work, try running the game without CV.
If it starts working, you’ll know that another mod is conflicting, and you’ll have to narrow it down — or there is an issue with CV specifically. In which case you’ll have to take it up with the mod author.
Hope this helps
-
- #4
Based on your client logs it seems like either some files are missing from the mod ClearVision, or there is another mod conflicting with the bundles that ClearVision edits.
I would start by reinstalling CV to see if that fixes it. If that doesn’t work, try running the game without CV.
If it starts working, you’ll know that another mod is conflicting, and you’ll have to narrow it down — or there is an issue with CV specifically. In which case you’ll have to take it up with the mod author.
Hope this helps
Display More
That’s a start and at least gives me a direction to go. What’s weird is I made a new profile, updated it so I’m back to where I was, and so far, the only issue I’ve had wasn’t from the ClearVision mod, but rather an insurance issue that kept hanging at the end of the raids. That was a minor inconvenience, but I fixed that myself. So far, this issue hasn’t come up again, yet I’m not running into the same issue. I’m wondering if it was an item I picked up? May have to look into it later, but for now, I’m at least playing again.
-
- #5
Guys!
I’ve got the same things what happened with me: I was playing on woods a Scavenger killed me with an AS-VAL (SP-5) Bullets. And after the session immediately the game has been crashed. …
The original game that I have been copied from Edge of Darkness edition
and the SPT-AKI version was also EOD.SPT-AKI Version: 3.0.0
Aki Server version: 14.15.3.0
Aki-Launcher.Exe version: 1.0.0.0
Ppatcher version: Patcher_12.12.30.18969_to_12.12.15.18346
I haven’t used any mods!
Here is my log files I hope that it helps to resolve the problem as fast as you canApplication-Log.txt
Backendlog-Ateg.txt
BepIndexLog-Ateg.txt
Errors-Log-Ateg.txt
TracersLog-Ateg.txt
If you would like to know any other info from the issue I can answer as fast as I see in the replies.
-
- #6
Update:
The known error: «Object reference not set to an instance of an object» appeared again but only once in about 10 raids.
Maybe someone with a bit technical knowledge could have a look at the attached error log.
So i had the error and may have a possible solution:
I had the same issue with my save and the following mods active:
— BandanaOfProtection
— ClearVision
— ServerValueModifier
After some trial and error i found that the issue could be related to increasing the size of containers above the values of standard and then using the extra space for items.
So i increased the size of a lucky scav box from 14×14 to 15×15 and filled it up. As soon as it was filled the system threw the error after every raid. I then emptied the box and the error disappeared.
I changed the size back to standard 14×14 and filled it up again and the error did not appear again. I will monitor everything for a while but it really looks like its related to the change of container size.
What i also found is that the issue could be related to weapons that are folded and the space they take changes. So unfold you weapons.
-
- #7
Update:
The known error: «Object reference not set to an instance of an object» appeared again but only once in about 10 raids.
Maybe someone with a bit technical knowledge could have a look at the attached error log.
So i had the error and may have a possible solution:
I had the same issue with my save and the following mods active:
— BandanaOfProtection
— ClearVision
— ServerValueModifier
After some trial and error i found that the issue could be related to increasing the size of containers above the values of standard and then using the extra space for items.
So i increased the size of a lucky scav box from 14×14 to 15×15 and filled it up. As soon as it was filled the system threw the error after every raid. I then emptied the box and the error disappeared.
I changed the size back to standard 14×14 and filled it up again and the error did not appear again. I will monitor everything for a while but it really looks like its related to the change of container size.
What i also found is that the issue could be related to weapons that are folded and the space they take changes. So unfold you weapons.
Display More
Right, but what further confuses me is that the issue is also arising for those that aren’t running mods. I can’t figure out why that’s happening.
-
- #8
Restarting the server fixed the problem for me
-
-
- #9
Restarting the server fixed the problem for me
…Oh, holy shit, that actually worked…I feel like a proper dunce now for not doing that. XD
-
CWX Jul 17th 2022
Closed the thread.
-
CWX Jul 17th 2022
Variables in .NET are either reference types or value types. Value types are primitives such as integers and booleans or structures (and can be identified because they inherit from System.ValueType). Boolean variables, when declared, have a default value:
bool mybool;
//mybool == false
Reference types, when declared, do not have a default value:
class ExampleClass
{
}
ExampleClass exampleClass; //== null
If you try to access a member of a class instance using a null reference then you get a System.NullReferenceException. Which is the same as Object reference not set to an instance of an object.
The following code is a simple way of reproducing this:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
returnedClass.AnotherExampleMethod(); //NullReferenceException here.
}
class ExampleClass
{
public ReturnedClass ExampleMethod()
{
return null;
}
}
class ReturnedClass
{
public void AnotherExampleMethod()
{
}
}
This is a very common error and can occur because of all kinds of reasons. The root cause really depends on the specific scenario that you’ve encountered.
If you are using an API or invoking methods that may return null then it’s important to handle this gracefully. The main method above can be modified in such a way that the NullReferenceException should never be seen by a user:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
if (returnedClass == null)
{
//throw a meaningful exception or give some useful feedback to the user!
return;
}
returnedClass.AnotherExampleMethod();
}
All of the above really just hints of .NET Type Fundamentals, for further information I’d recommend either picking up CLR via C# or reading this MSDN article by the same author — Jeffrey Richter. Also check out, much more complex, example of when you can encounter a NullReferenceException.
Some teams using Resharper make use of JetBrains attributes to annotate code to highlight where nulls are (not) expected.
Variables in .NET are either reference types or value types. Value types are primitives such as integers and booleans or structures (and can be identified because they inherit from System.ValueType). Boolean variables, when declared, have a default value:
bool mybool;
//mybool == false
Reference types, when declared, do not have a default value:
class ExampleClass
{
}
ExampleClass exampleClass; //== null
If you try to access a member of a class instance using a null reference then you get a System.NullReferenceException. Which is the same as Object reference not set to an instance of an object.
The following code is a simple way of reproducing this:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
returnedClass.AnotherExampleMethod(); //NullReferenceException here.
}
class ExampleClass
{
public ReturnedClass ExampleMethod()
{
return null;
}
}
class ReturnedClass
{
public void AnotherExampleMethod()
{
}
}
This is a very common error and can occur because of all kinds of reasons. The root cause really depends on the specific scenario that you’ve encountered.
If you are using an API or invoking methods that may return null then it’s important to handle this gracefully. The main method above can be modified in such a way that the NullReferenceException should never be seen by a user:
static void Main(string[] args)
{
var exampleClass = new ExampleClass();
var returnedClass = exampleClass.ExampleMethod();
if (returnedClass == null)
{
//throw a meaningful exception or give some useful feedback to the user!
return;
}
returnedClass.AnotherExampleMethod();
}
All of the above really just hints of .NET Type Fundamentals, for further information I’d recommend either picking up CLR via C# or reading this MSDN article by the same author — Jeffrey Richter. Also check out, much more complex, example of when you can encounter a NullReferenceException.
Some teams using Resharper make use of JetBrains attributes to annotate code to highlight where nulls are (not) expected.