When I execute some code, a NullReferenceException with the following message:
Object reference not set.
or
Object reference not set to an instance of an object.
What does this mean, and how do I fix the code?
You are trying to use something that is null (or Nothing in VB.NET). This means that either you assigned this value or you assigned nothing.
Like any other value, null can be passed from object to object, from method to method. If something is null in method "A", it may well be that method "B" passed this value to method "A".
The rest of the article describes what's happening in detail and lists common errors that could lead to a NullReferenceException .
If the runtime throws a NullReferenceException exception, it always means one thing: you are trying to use the link. And this link is not initialized (or was initialized, but not already initialized).
This means that the link is null , and you cannot call methods through a link that is null . In the simplest case:
string foo = null; foo.ToUpper(); This code will throw a NullReferenceException exception on the second line, because you cannot call the ToUpper() method of the ToUpper() reference to the string .
How to determine the source of the error? In addition to studying the exception itself, which will be thrown exactly where it occurred, you can use general debugging guidelines in Visual Studio: put breakpoints at key points, study the values of variables either by placing the mouse cursor over the variable, or by opening the debug panels: Watch, Locals, Autos.
If you want to determine the place where the link value is set or not set, right-click on its name and select "Find All References". Then you can set breakpoints on each line found and start the application in debug mode. Every time the debugging stops at a breakpoint, you can make sure that the value is correct.
Following the progress of the program, you will come to a place where the value of the link should not be null , and determine why the correct value is not assigned.
Some common examples in which an exception occurs.
ref1.ref2.ref3.member If ref1 , ref2 or ref3 is null , you will get a NullReferenceException . To solve the problem and determine what exactly is null , you can rewrite the expression in a simpler way:
var r1 = ref1; var r2 = r1.ref2; var r3 = r2.ref3; r3.member For example, in the HttpContext.Current.User.Identity.Name chain, the value may be missing for HttpContext.Current , User , and Identity .
public class Person { public int Age { get; set; } } public class Book { public Person Author { get; set; } } public class Example { public void Foo() { Book b1 = new Book(); int authorAge = b1.Author.Age; // Свойство Author не было инициализировано // нет Person, у которого можно вычислить Age. } } The same is true for nested initializers:
Book b1 = new Book { Author = { Age = 45 } }; Despite the use of the new keyword, only an instance of the Book class is created, but the Person instance is not created, so the Author property remains null .
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]. Dictionary<string, int> agesForNames = null; int age = agesForNames["Bob"]; // agesForNames = null. // Экземпляр словаря не создан. 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 никто не подписался } } If the local variables and fields had different names in the code below, you would find that the field was not initialized:
public class Form1 { private Customer customer; private void Form1_Load(object sender, EventArgs e) { Customer customer = new Customer(); customer.Name = "John"; } private void Button_Click(object sender, EventArgs e) { MessageBox.Show(customer.Name); } } You can avoid problems by using the prefix for the fields:
private Customer _customer; 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 здесь!"; } } // Если сессионная переменная "FirstName" ещё не была задана, // то эта строка бросит NullReferenceException. string firstName = Session["FirstName"].ToString(); If you return an empty model (or model property) in the controller, I twist an exception when trying to access it:
// Controller public class Restaurant:Controller { public ActionResult Search() { return View(); // Модель не задана. } } // Razor view @foreach (var restaurantSearch in Model.RestaurantSearch) // Исключение. { } null , skip codeIf you expect the link to be null in some cases, you can explicitly check this value before accessing the members of the instance:
void PrintName(Person p) { if (p != null) { Console.WriteLine(p.Name); } } null , use defaultMethods can return null , for example, if the required instance is not found. In this case, you can return the default value:
string GetCategory(Book b) { if (b == null) return "Unknown"; return b.Category; } null , throw your exceptionYou can also throw your exception to catch it later:
string GetCategory(string bookTitle) { var book = library.FindBook(bookTitle); // Может вернуть null if (book == null) throw new BookNotFoundException(bookTitle); // Ваше исключение return book.Category; } Debug.Assert to check for null to detect errors before throwing an exceptionIf during development you know that a method can, but generally should not return null , you can use Debug.Assert to quickly find errors:
string GetTitle(int knownBookID) { // Вы знаете, что метод не должен возвращать null var book = library.GetBook(knownBookID); // Исключение будет выброшено сейчас, а не в конце метода. Debug.Assert(book != null, "Library didn't return a book for known book ID."); // Остальной код... return book.Title; // Не выбросит NullReferenceException в режиме отладки. } However, this check will not work in the release build, and you will again get a NullReferenceException if book == null .
GetValueOrDefault() for Nullable Types DateTime? appointment = null; Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Отобразит значение по умолчанию, потому что appointment = null. appointment = new DateTime(2022, 10, 20); Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Отобразит дату, а не значение по умолчанию. ?? (C #) or If() (VB)A brief entry to set the default values:
IService CreateService(ILogger log, Int32? frobPowerLevel) { var serviceImpl = new MyService(log ?? NullLog.Instance); serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5; } ?. and ?[ (C # 6+, VB.NET 14+):This is the operator of secure access to members, also known as the operator of Elvis for a specific form. If the expression to the left of the operator is null , then the right side is ignored, and the result is considered null . For example:
var title = person.Title.ToUpper(); If the Title property is null , an exception will be thrown, because this is an attempt to call the ToUpper method on a null value. In C # 5 and below, you can add a check:
var title = person.Title == null ? null : person.Title.ToUpper(); Now, instead of throwing an exception, the title variable will be set to null . A shorter syntax has been added to C # 6:
var title = person.Title?.ToUpper(); Of course, if the person variable can be null , then you need to check it too. You can also use the operators ?. and ?? together to provide a default value:
// обычная проверка на null int titleLength = 0; if (title != null) titleLength = title.Length; // совмещаем операторы `?.` и `??` int titleLength = title?.Length ?? 0; If any member in the chain can be null , then you can fully protect yourself (although, of course, the architecture should be questioned):
int firstCustomerOrderCount = customers?[0]?.Orders?.Count() ?? 0; null and ignore the error (which hides a bug, but does not contribute to correcting it), but correct the code, which should guarantee that there will be no null . - VladDnull valid. Then, probably, the first question should be: is null valid at this point? If so, you need a null check and an adequate response. If not, then the code is correct, and the problem is somewhere before (most likely in the initialization). - VladDref1?.ref2?.ref3?.member - AK ♦In addition to the @Discord @Squidward @Athari answer, let's look at the question from the other side.
If you had a NullReferenceException while NullReferenceException when accessing a link, you should first ask yourself an important question:
Does this link have the right to be
null?
In many cases, the correct answer is “no,” which means that you will have to correct the true cause of the error, which is in a different place, and happened earlier.
Example: if you have this class:
class Car { Engine engine; Driver driver; // ... остаток класса } So, the motor at the car must be in any case, always. But the driver can, in principle, and not sit in the car.
Therefore, if you see that the call to the engine.HorsePower falls with a NullReferenceException , the real problem is that you forgot to initialize the engine in the constructor. Therefore, you need to correct the error not at the point where it falls, but in the place that would really provide a non-zero engine value.
But if the driver.Age application driver.Age , then there is already a problem right at the point of contact, you must first check that driver != null , and then you can contact us.
Thus: if your link at the reference point does not have the right to be null , then you should not add a check to null , thereby "glossing over" the error. You should either not check anything, but fix it in the place where the link should be initialized, or add Debug.Assert , or check for null and throw an exception.
If the link has the right to be null , then in this case it is necessary to correctly handle this case as well.
Important note: If your function is called "outside world", you should not expect that good, correct arguments will be passed to your function. Even if you require that the object that is passed to you is not null , you can still pass the wrong object to you. Therefore, for functions available to external modules, it is necessary to check the arguments for null immediately at the beginning of the code, and throw the necessary exception:
public decimal ComputePrice(Car car) { if (car == null) throw new ArgumentNullException("car"); // ... Where exactly to draw the line between the "inner" and "outer" world, the question is rather nontrivial. Usually this border is the border of the module (assembly), or even that logical part of it, which is your responsibility. Too small fragmentation leads to the repetition of meaningless code (one part of the program does not trust the other and constantly re-checks it). Too large a split leads to the need to keep millions of dependencies in mind (“can I transmit null here or not?”). Use common sense and personal experience.
C # 8 finally introduces a clear distinction between the two cases. For those links that may contain null , a special syntax is #nullable enable ( #nullable enable must be enabled in the file (or in the <NullableContextOptions>enable</NullableContextOptions> project ):
class Car { Engine engine; // не может быть null Driver? driver; // может быть null // ... остаток класса } In this case, the compiler itself will be able to check that you forgot to initialize the value of the engine field and give you a warning.
? And not the "non-nullable reference type" with the modifier will be entered ! will be used to extract the value, not the variable definition). - AthariT! . Although you're right, I'll change the link. - VladD! when declared is discussed only in the context of parameters of generic types. As I understand it, your example should be of the form Engine engine; Driver? driver; Engine engine; Driver? driver; . - AthariThank you for your interest in this issue. Since he collected a large number of low-quality and spam responses, which had to be deleted, now it’s necessary to have 10 reputation points on the site (the bonus for account association is not counted ).
Maybe you want to answer one of the unanswered questions ?
Source: https://ru.stackoverflow.com/questions/722176/
All Articles
?.to add. It seems not visible in the answer. - Qwertiy ♦