0 Вопрос: Почему я не получаю ссылку на объект в качестве экземпляра ошибки объекта? [Дубликат]

вопрос создан в Wed, May 8, 2019 12:00 AM

У меня есть некоторый код, и когда он выполняется, он выдает NullReferenceException, говоря:

  

Ссылка на объект не установлена ​​на экземпляр объекта.

Что это значит и что я могу сделать, чтобы исправить эту ошибку?

    
1877
  1. Помощник по исключениям в VS 2017 будет более полезен при диагностике причины этого исключения - blogs.msdn.microsoft.com/visualstudio/2016/11/28/… в разделе Помощник нового исключения .
    2016-12-29 09: 06: 19Z
  2. Уважаемые будущие посетители, ответы на этот вопрос в равной степени относятся к ArgumentNullException . Если ваш вопрос был закрыт как дубликат этого вопроса, и вы испытываете ANE, следуйте инструкциям в ответах, чтобы отладить и исправить вашу проблему.
    2017-10-13 17: 56: 23Z
  3. @ будет ANE должно произойти, только если в качестве параметра передается значение NULL. Можете ли вы привести пример, если вопрос ANE закрыт как дубликат этого вопроса?
    2017-10-14 21: 44: 46Z
  4. Это появилось в Meta, но мне нужно было поискать ссылку. Но что касается этого комментария, ANE - это просто NRE, но кто-то добавил упреждающую проверку, и вы, по крайней мере, точно знаете, что такое null (имя аргумента указано), так что диагностировать немного проще, чем NRE с прямым доступом.
    2017-10-16 12: 53: 02Z
    30 ответов                              30                         

    В чем причина?

    Итог

    Вы пытаетесь использовать что-то null (или Nothing в VB.NET). Это означает, что вы либо установите его на null, либо никогда вообще ничего не устанавливаете.

    Как и все остальное, null раздают. Если это null в методе "A", возможно, этот метод "B" передал null в метод "A".

    null может иметь разные значения:

    1. Переменные объекта, которые неинициализированы и, следовательно, ни на что не указывают. В этом случае, если вы обращаетесь к свойствам или методам таких объектов, это вызывает NullReferenceException.
    2. Разработчик использует null преднамеренно, чтобы указать, что значимых доступных значений нет. Обратите внимание, что в C # существует концепция типов данных, допускающих обнуляемость (например, в таблицах базы данных могут быть поля, обнуляемые) - вы можете назначить null им указать, что в нем нет сохраненного значения, например, int? a = null;, где вопросительный знак указывает, что ему разрешено хранить ноль в переменной a. Вы можете проверить, что либо с if (a.HasValue) {...}, либо с if (a==null) {...}. Обнуляемые переменные, например, 060000, как, например, 06003 чтобы получить доступ к значению через a явным образом или просто как обычно через a.Value.
      Примечание , которое получает доступ к нему через a, выдает a.Value вместо 0600350991100101035062, а вы 060600505011111100005062626262626262620000000000000000000011110000000011110000000000111100000000111100000000001111000000000011110000000000001111000000110000001100000011000000110000000000110000001100000011000000000011110000506211000000111100001160000000011110000005062, если 0600350505011110000005062, если вы хотите получить доступ к значению с помощью InvalidOperationException т.е. если вы есть еще одна переменная on-nullable NullReferenceException, тогда вы должны делать назначения, такие как a или короче null.

    В остальной части этой статьи более подробно рассматриваются ошибки, которые часто допускают многие программисты, что может привести к int b;.

    Более конкретно

    Время выполнения, выбрасывающее if (a.HasValue) { b = a.Value; } всегда , означает то же самое: вы пытаетесь использовать ссылку, и ссылка не инициализирована (или она была однажды инициализирована, но больше не инициализируется).

    Это означает, что ссылка if (a != null) { b = a; }, и вы не можете получить доступ к членам (например,как методы) через ссылку NullReferenceException. Самый простой случай:

    NullReferenceException

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

    string foo = null;
    foo.ToUpper();
    
    , указывающей на NullReferenceException.

    Отладка

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

    Если вы хотите узнать, где находится ссылка или нет, щелкните правой кнопкой мыши ее имя и выберите «Найти все ссылки». Затем вы можете установить точку останова в каждом найденном месте и запустить программу с подключенным отладчиком. Каждый раз, когда отладчик прерывает работу на такой точке останова, вам нужно определить, ожидаете ли вы, что ссылка не равна нулю, проверить переменную и убедиться, что она указывает на экземпляр, когда вы этого ожидаете.

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

    Примеры

    Некоторые распространенные сценарии, в которых может быть выдано исключение:

    Generic

    string

    Если ref1 или ref2 или ref3 равны нулю, вы получите null. Если вы хотите решить проблему, выясните, какая из них пуста, переписав выражение в его более простой эквивалент:

    NullReferenceException

    В частности, в

    ref1.ref2.ref3.member
    
    значение NullReferenceException может быть равно нулю, либо свойство
    var r1 = ref1;
    var r2 = r1.ref2;
    var r3 = r2.ref3;
    r3.member
    
    может быть равно нулю, либо свойство HttpContext.Current.User.Identity.Name может быть равно нулю.

    Косвенный

    HttpContext.Current

    Если вы хотите избежать нулевой ссылки дочернего (Person), вы можете инициализировать ее в конструкторе родительского (Book) объекта.

    Инициализаторы вложенных объектов

    То же самое относится и к инициализаторам вложенных объектов:

    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; // You never initialized the Author property.
                                           // there is no Person to get an Age from.
        }
    }
    
    , оно создает только новый экземпляр
    Book b1 = new Book { Author = { Age = 45 } };
    
    , но не новый экземпляр
    Book b1 = new Book();
    b1.Author.Age = 45;
    
    , поэтому свойство new по-прежнему Book.

    Инициализаторы вложенных коллекций

    Person

    Инициализаторы вложенных коллекций ведут себя одинаково:

    Author

    Это переводится как

    null

    public class Person {
        public ICollection<Book> Books { get; set; }
    }
    public class Book {
        public string Title { get; set; }
    }
    
    создает только экземпляр
    Person p1 = new Person {
        Books = {
            new Book { Title = "Title1" },
            new Book { Title = "Title2" },
        }
    };
    
    , но коллекция
    Person p1 = new Person();
    p1.Books.Add(new Book { Title = "Title1" });
    p1.Books.Add(new Book { Title = "Title2" });
    
    по-прежнему new Person. Синтаксис инициализатора коллекции не создает коллекцию для Person он преобразуется только в операторы Books.

    Массив

    null

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

    p1.Books

    Зубчатые массивы

    p1.Books.Add(...)

    Коллекция /Список /Словарь

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

    Переменная диапазона (косвенная /отложенная)

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

    События

    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.
    

    Соглашения о недопустимом наименовании:

    Если вы назвали поля не так, как местные, вы могли бы понять, что никогда не инициализировали поле.

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

    Эту проблему можно решить, следуя соглашению о добавлении префикса к полям с подчеркиванием:

    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.
    

    Жизненный цикл страницы ASP.NET:

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

    Значения сеанса ASP.NET

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

    ASP.NET MVC модели пустого представления

    Если исключение возникает при обращении к свойству

    private Customer _customer;
    
    в представлении ASP.NET MVC, необходимо понимать, что
    public partial class Issues_Edit : System.Web.UI.Page
    {
        protected TestIssue myIssue;
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Only called on first load, not when button clicked
                myIssue = new TestIssue(); 
            }
        }
    
        protected void SaveButton_Click(object sender, EventArgs e)
        {
            myIssue.Entry = "NullReferenceException here!";
        }
    }
    
    устанавливается в вашем методе действия, когда вы
    // if the "FirstName" session value has not yet been set,
    // then this line will throw a NullReferenceException
    string firstName = Session["FirstName"].ToString();
    
    просматриваете. Когда вы возвращаете пустую модель (или свойство модели) из вашего контроллера, исключение возникает, когда представления обращаются к нему: @Model

    Порядок и события создания элемента управления WPF

    Элементы управления WPF создаются во время вызова Model в порядке их появления в визуальном дереве. return будет вызываться в случае ранее созданных элементов управления с обработчиками событий и т. Д., Которые срабатывают во время

    // Controller
    public class Restaurant:Controller
    {
        public ActionResult Search()
        {
             return View();  // Forgot the provide a Model here.
        }
    }
    
    // Razor view 
    @foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
    {
    }
    
    <p>@Model.somePropertyName</p> <!-- Also throws -->
    
    , которые ссылаются на недавно созданные элементы управления.

    Например:

    InitializeComponent

    Здесь NullReferenceException создается до InitializeComponent. Если

    <Grid>
        <!-- Combobox declared first -->
        <ComboBox Name="comboBox1" 
                  Margin="10"
                  SelectedIndex="0" 
                  SelectionChanged="comboBox1_SelectionChanged">
            <ComboBoxItem Content="Item 1" />
            <ComboBoxItem Content="Item 2" />
            <ComboBoxItem Content="Item 3" />
        </ComboBox>
    
        <!-- Label declared later -->
        <Label Name="label1" 
               Content="Label"
               Margin="10" />
    </Grid>
    
    пытается сослаться на `label1, он еще не был создан. comboBox1

    Изменение порядка объявлений в XAML (т. е. список 060035099111100101035)062 до label1, игнорируя проблемы философии дизайна, по крайней мере разрешит comboBox1_SelectionChanged здесь.

    В ролях с
    private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!!
    }
    

    label1

    Это не вызывает InvalidCastException, но возвращает comboBox1, когда приведение не выполнено (и когда someObject само по себе равно null). Так что знайте об этом.

    LINQ FirstOrDefault () и SingleOrDefault ()

    Простые версии NullReferenceException и as генерируют исключения, когда ничего нет. Версии «OrDefault» в этом случае возвращают ноль. Так что знайте об этом.

    Еогеасп

    var myThing = someObject as Thing;
    
    выбрасывает при попытке перебрать нулевую коллекцию. Обычно вызвано неожиданным результатом null из методов, возвращающих коллекции. First()

    Более реалистичный пример - выберите узлы из XML-документа. Выдает, если узлы не найдены, но начальная отладка показывает, что все свойства действительны:

    Single()

    Пути, которых следует избегать

    Явная проверка foreach и игнорирование нулевых значений.

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

     List<int> list = null;    
     foreach(var v in list) { } // exception
    

    Явно проверьте
     foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))
    
    и укажите значение по умолчанию.

    Вызов методов, которые вы ожидаете вернуть, может вернуть 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);  // This may return null
        if (book == null)
            throw new BookNotFoundException(bookTitle);  // Your custom exception
        return book.Category;
    }
    
    для прерывания как можно скорее, когда это произойдет: Debug.Assert

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

    Используйте Debug.Assert() для типов значений, допускающих значение NULL, чтобы обеспечить значение по умолчанию, когда они равны
    string GetTitle(int knownBookID) {
        // You know this should never return null.
        var book = library.GetBook(knownBookID);  
    
        // Exception will occur on the next line instead of at the end of this method.
        Debug.Assert(book != null, "Library didn't return a book for known book ID.");
    
        // Some other code
    
        return book.Title; // Will never throw NullReferenceException in Debug mode.
    }
    
    .

    NullReferenceException

    Используйте оператор объединения нулей: book == null [C #] или GetValueOrDefault() [VB].

    Сокращение для предоставления значения по умолчанию при обнаружении 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
    

    Используйте нулевой оператор условия: ?? или If() для массивов (доступно в C # 6 и VB.NET 14):

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

    null

    Если у человека нет заголовка, это вызовет исключение, потому что он пытается вызвать

    IService CreateService(ILogger log, Int32? frobPowerLevel)
    {
        var serviceImpl = new MyService(log ?? NullLog.Instance);
    
        // Note that the above "GetValueOrDefault()" can also be rewritten to use
        // the coalesce operator:
        serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
    }
    
    для свойства со значением NULL.

    В C # 5 и ниже это может быть защищено с помощью:

    ?.

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

    ?[x]

    Это приведет к тому, что переменная заголовка будет

    var title = person.Title.ToUpper();
    
    , и вызов ToUpper не будет выполнен, если
    var title = person.Title == null ? null : person.Title.ToUpper();
    
    равен
    var title = person.Title?.ToUpper();
    
    .

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

    person.Title

    Аналогично, для массивов вы можете использовать null следующим образом:

    title

    Это сделает следующее: если myIntArray имеет значение null, выражение возвращает значение null, и вы можете безопасно проверить его. Если он содержит массив, он будет делать то же самое, что и: ?? и возвращает элемент i th .

    Специальные методы отладки и исправления нулевых разыменований в итераторах

    C # поддерживает «блоки итераторов» (называемые «генераторами» в некоторых других популярных языках). Исключения нулевого разыменования могут быть особенно сложными для отладки в блоках итератора из-за отложенного выполнения:

    // regular null check
    int titleLength = 0;
    if (title != null)
        titleLength = title.Length; // If title is null, this would throw NullReferenceException
    
    // combining the `?` and the `??` operator
    int titleLength = title?.Length ?? 0;
    

    Если ?[i] приводит к

    int[] myIntArray=null;
    var i=5;
    int? elem = myIntArray?[i];
    if (!elem.HasValue) Console.WriteLine("No value");
    
    , то elem = myIntArray[i]; выбросит. Теперь вы можете подумать, что правильно сделать следующее:
    public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
    {
        for (int i = 0; i < count; ++i)
          yield return f.MakeFrob();
    }
    ...
    FrobFactory factory = whatever;
    IEnumerable<Frobs> frobs = GetFrobs();
    ...
    foreach(Frob frob in frobs) { ... }
    

    Почему это не так?Потому что блок итератора фактически не запускается до whatever! Вызов null просто возвращает объект, который при повторении будет запускать блок итератора.

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

    Правильное исправление:

    MakeFrob

    То есть создайте приватный вспомогательный метод, который имеет логику блока итератора, и метод публичной поверхности, который выполняет нулевую проверку и возвращает итератор. Теперь, когда вызывается

    // DON'T DO THIS
    public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
    {
        if (f == null) 
          throw new ArgumentNullException("f", "factory must not be null");
        for (int i = 0; i < count; ++i)
          yield return f.MakeFrob();
    }
    
    , проверка нуля происходит немедленно, а затем foreach выполняется, когда последовательность повторяется.

    Если вы изучите источник ссылок для LINQ to Objects, вы увидите, что этот метод используется повсеместно. Это немного более неуклюже, чтобы написать, но это делает отладку ошибок недействительности намного легче. Оптимизируйте свой код для удобства звонящего, а не для удобства автора .

    Примечание о нулевых разыменованиях в небезопасном коде

    C # имеет «небезопасный» режим, который, как следует из названия, чрезвычайно опасен, потому что обычные механизмы безопасности, которые обеспечивают безопасность памяти и безопасность типов, не применяются. Вы не должны писать небезопасный код, если у вас нет глубокого и глубокого понимания того, как работает память .

    В небезопасном режиме вы должны знать о двух важных фактах:

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

    Чтобы понять, почему это так, полезно понять, как .NET в первую очередь создает исключения с нулевым разыменованием. (Эти сведения относятся к .NET, работающему в Windows; другие операционные системы используют аналогичные механизмы.)

    Память виртуализирована в Windows; каждый процесс получает пространство виртуальной памяти из множества «страниц» памяти, которые отслеживаются операционной системой. На каждой странице памяти установлены флаги, которые определяют, как ее можно использовать: чтение, запись, выполнение и т. Д. Страница наименьшего помечена как «выдает ошибку, если когда-либо использовалась каким-либо образом».

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

    Вот почему разыменование как нулевого указателя, так и нулевой ссылки создает одно и то же исключение.

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

    Почему это имеет смысл? Хорошо, предположим, что у нас есть структура, содержащая два целых числа и неуправляемый указатель, равный нулю. Если мы попытаемся разыменовать второе int в структуре, CLR не будет пытаться получить доступ к хранилищу в нулевом местоположении; он получит доступ к хранилищу в расположении четыре. Но логически это нулевая разыменование, потому что мы получаем по этому адресу через ноль.

    Если вы работаете с небезопасным кодом и получаете исключение нулевой разыменования, просто имейте в виду, что указатель-нарушитель не обязательно должен быть нулевым. Это может быть любое место на самой нижней странице, и будет создано это исключение.

        
    2258
    2018-07-18 06: 27: 33Z
    1. Может быть, это глупый комментарий, но первым и лучшим способом избежать этой проблемы является инициализация объекта? Для меня, если эта ошибка происходит, это обычно потому, что я забыл инициализировать что-то вроде элемента массива. Я думаю, что гораздо реже определять объект как нулевой, а затем ссылаться на него. Может быть, дать способ решить каждую проблему, смежную с описанием. Все еще хороший пост.
      2014-05-20 06: 39: 13Z
    2. Что делать, если нет объекта, а скорее возвращаемое значение из метода или свойства?
      2014-05-20 06: 41: 02Z
    3. Пример книги /автора немного странный .... Как это вообще компилируется? Как работает intellisense? Что это, я не очень хорошо разбираюсь в компьютерах ...
      2014-09-08 18: 26: 23Z
    4. @ Will: поможет ли мое последнее редактирование? Если нет, то, пожалуйста, будьте более откровенны в том, что вы считаете проблемой.
      2014-09-08 18: 41: 50Z
    5. @ JohnSaunders О, нет, извините, я имел в виду версию инициализатора объекта этого. GetFrobs Как внутренняя инициализация даже ... Я не могу представить ситуацию, когда внутренний init когда-либо будет работать, но он компилируется и работает intellisense ... Если не для структур?
      2014-09-08 18: 44: 35Z

    Исключение NullReference - Visual Basic

    // DO THIS
    public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
    {
        // No yields in a public method that throws!
        if (f == null) 
          throw new ArgumentNullException("f", "factory must not be null");
        return GetFrobsForReal(f, count);
    }
    private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
    {
        // Yields in a private method
        Debug.Assert(f != null);
        for (int i = 0; i < count; ++i)
          yield return f.MakeFrob();
    }
    
    для Visual Basic ничем не отличается от C # . В конце концов, они оба сообщают об одном и том же исключении, определенном в .NET Framework, которое они оба используют. Причины, уникальные для Visual Basic, встречаются редко (возможно, только одна).

    В этом ответе будут использоваться термины, синтаксис и контекст Visual Basic. Используемые примеры взяты из большого количества прошлых вопросов о переполнении стека. Это сделано для максимизации релевантности, используя виды ситуаций, часто встречающихся в постах. Немного больше объяснений также предоставляется тем, кому это может понадобиться. Пример, похожий на ваш, очень , скорее всего, приведен здесь.

    Примечание:

    1. Это основано на концепции: нет кода для вставки в ваш проект. Он предназначен для того, чтобы помочь вам понять, что вызывает GetFrobs (NRE), как его найти, как его исправить и как его избежать. NRE может быть вызвано разными способами, так что вряд ли это будет ваша единственная встреча.
    2. Примеры (из сообщений Stack Overflow) не всегда показывают лучший способ сделать что-либо в первую очередь.
    3. Как правило, используется самое простое средство правовой защиты.

    Основное значение

    Сообщение «Объект не установлен как экземпляр объекта» означает, что вы пытаетесь использовать объект, который не был инициализирован. Это сводится к одному из них:

    • Ваш код объявил переменную объекта, но он не инициализировал ее (создавал экземпляр или создавал 'его)
    • То, что предполагалось в вашем коде, будет инициализировать объект, не так
    • Возможно, другой код преждевременно объявил недействительным объект, который все еще используется

    В поисках причины

    Поскольку проблема заключается в ссылке на объект GetFrobsForReal, ответ состоит в том, чтобы изучить их, чтобы выяснить, какая из них. Затем определите, почему он не инициализирован. Наведите указатель мыши на различные переменные, и Visual Studio (VS) покажет их значения - виновником будет new Book { Author = { Age = 45 } };.

    Отображение отладки IDE

    Вы также должны удалить все блоки Try /Catch из соответствующего кода, особенно те, где в блоке Catch ничего нет. Это приведет к сбою вашего кода при попытке использовать объект NullReference Exception. Это то, что вам нужно , так как он определит точное местоположение проблемы и позволит вам идентифицировать объект, вызывающий его.

    NullReferenceException в улове, который отображает Nothing, мало поможет. Этот метод также приводит к очень плохим вопросам переполнения стека, потому что вы не можете описать фактическое исключение, задействованный объект или даже строку кода, где это происходит.

    Вы также можете использовать Nothing ( Debug -> Windows -> Locals ) для проверки своих объектов.

    Как только вы знаете, в чем и где проблема, ее обычно довольно легко устранить и быстрее, чем опубликовать новый вопрос.

    Смотрите также:

    Примеры и средства правовой защиты

    Объекты класса /Создание экземпляра

    Nothing

    Проблема в том, что MsgBox не создает объект CashRegister ; он только объявляет переменную с именем Error while... этого типа. Объявление объектной переменной и создание экземпляра - это разные вещи.

    Устранение

    Оператор Locals Window часто можно использовать для создания экземпляра при его объявлении:

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

    Когда это подходит только длясоздайте экземпляр позже:

    Dim

    Примечание. Не снова используйте reg в процедуре, включая конструктор (New):

    Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor
    
    ' Longer, more explicit form:
    Dim reg As CashRegister = New CashRegister
    

    Это создаст локальную переменную,

    Private reg As CashRegister         ' Declare
      ...
    reg = New CashRegister()            ' Create instance
    
    , которая существует только в этом контексте (подпункте). Переменная Dim с уровнем модуля Sub New, которую вы будете использовать везде, остается
    Private reg As CashRegister
    '...
    
    Public Sub New()
       '...
       Dim reg As New CashRegister
    End Sub
    
    .
      

    Отсутствие оператора reg является причиной № 1 reg , замеченной в рассмотренных вопросах переполнения стека.

         

    Visual Basic несколько раз пытается очистить процесс, используя Scope : с помощью оператора Nothing создается объект new и вызывается New - конструктор - где ваш объект может выполнить любую другую инициализацию.

    Для ясности, NullReference Exceptions (или New) только объявляет переменную и ее New. Область действия переменной - существует ли она для всего модуля /класса или является локальным для процедуры - определяется где она объявлена. Sub New определяет уровень доступа, а не Область .

    Для получения дополнительной информации см .:

    Массивы

    Массивы также должны быть созданы:

    Dim

    Этот массив только объявлен, но не создан. Существует несколько способов инициализации массива:

    Private

    Примечание. Начиная с VS 2010, при инициализации локального массива с использованием литерала и Type элементы Private | Friend | Public и

    Private arr as String()
    
    являются необязательными:
    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) {}
    

    Тип данных и размер массива выводятся из назначаемых данных. Для объявлений уровня класса /модуля по-прежнему требуется Option Infer с As <Type>:

    New

    Пример: массив объектов класса

    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}
    

    Массив создан, но объекты As <Type> в нем нет.

    Устранение

    Option Strict

    Использование

    Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}
    
    усложнит создание элемента без действительного объекта:
    Dim arrFoo(5) As Foo
    
    For i As Integer = 0 To arrFoo.Count - 1
       arrFoo(i).Bar = i * 10       ' Exception
    Next
    

    Для получения дополнительной информации см .:

    Списки и коллекции

    Коллекции .NET (из которых существует множество разновидностей - списки, словарь и т. д.) также должны быть созданы или созданы.

    Foo

    По той же причине вы получаете то же исключение -

    For i As Integer = 0 To arrFoo.Count - 1
        arrFoo(i) = New Foo()         ' Create Foo instance
        arrFoo(i).Bar = i * 10
    Next
    
    было объявлено только, но экземпляр не создан. Средство защиты такое же: List(Of T)

    Общий надзор - это класс, который использует коллекцию

    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
    
    :
    Private myList As List(Of String)
    ..
    myList.Add("ziggy")           ' NullReference
    

    Любая процедура приведет к NRE, потому что myList только объявлен, но не создан. Создание экземпляра

    myList = New List(Of String)
    
    ' Or create an instance when declared:
    Private myList As New List(Of String)
    
    также не создаст экземпляр внутреннего 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
    

    Как и раньше, это неверно:

    barList

    Для получения дополнительной информации см. Foo Class а>. р>

    Объекты провайдера данных

    Работа с базами данных предоставляет много возможностей для NullReference, потому что может быть много объектов (barList,

    Public Sub New         ' Constructor
        ' Stuff to do when a new Foo is created...
        barList = New List(Of Bar)
    End Sub
    
    ,
    Public Sub New()
        ' Creates another barList local to this procedure
         Dim barList As New List(Of Bar)
    End Sub
    
    , List(Of T), Command, Connection ....) одновременно. Примечание. . Не имеет значения, какой поставщик данных вы используете - MySQL, SQL Server, OleDB и т. д. - понятия совпадают.

    Пример 1

    Transaction

    Как и прежде, объект набора данных Dataset был объявлен, но экземпляр так и не был создан. DataTable заполнит существующий DataRows, а не создаст его. В этом случае, поскольку

    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
    
    является локальной переменной, IDE предупреждает вас о том, что это может произойти:

    img

    При объявлении в качестве переменной уровня модуля /класса, как это имеет место в случае с ds, компилятор не может знать, был ли объект создан в восходящей процедуре. Не игнорируйте предупреждения.

    Устранение

    DataAdapter

    Пример 2

    DataSet

    Опечатка является проблемой здесь: ds против con. Не было создано

    Dim ds As New DataSet
    
    с именем "Employee", поэтому результаты
    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)
    
    пытаются получить к нему доступ. Другая потенциальная проблема заключается в предположении, что будет Employees, чего не может быть, когда SQL включает предложение WHERE.

    Устранение

    Поскольку здесь используется одна таблица, использование Employee позволит избежать орфографических ошибок. Изучение DataTable также может помочь:

    NullReferenceException

    Items - это функция, возвращающая число затронутых Tables(0), которое также можно проверить:

    Rows.Count

    Пример 3

    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 предоставит Rows, как показано в предыдущем примере, но не анализирует имена из таблицы SQL или базы данных. В результате

    If da.Fill(ds, "Employees") > 0 Then...
    
    ссылается на несуществующую таблицу.

    Средство правовой защиты такое же, ссылка на таблицу по индексу:

    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
    

    См. также класс DataTable . р>

    Пути к объектам /вложенные

    DataAdapter

    Код тестирует только TableNames, в то время как ds.Tables("TICKET_RESERVATION") и

    If ds.Tables(0).Rows.Count > 0 Then
    
    также могут быть Nothing. Средство защиты - проверять всю цепочку или путь объектов по одному:

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

    Items важно. Последующие тесты не будут выполнены после того, как будет найдено первое условие myFoo. Это позволяет коду безопасно «углубляться» в объект (ы) по одному «уровню» за раз, оценивая Bar только после того, как (и если)

    If (myFoo IsNot Nothing) AndAlso
        (myFoo.Bar IsNot Nothing) AndAlso
        (myFoo.Bar.Items IsNot Nothing) Then
        ....
    
    будет признан действительным. Цепочки объектов или пути могут быть довольно длинными при кодировании сложных объектов: AndAlso

    Невозможно ссылаться на что-либо «ниже по потоку» объекта False. Это также относится к элементам управления:

    myFoo.Bar

    Здесь myFoo или

    myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")
    
    могут иметь значение Nothing или элемент null может не существовать.

    Элементы управления пользовательским интерфейсом

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

    Помимо прочего, этот код не предполагает, что пользователь, возможно, не выбрал что-то в одном или нескольких элементах управления пользовательского интерфейса. myWebBrowser вполне может быть Document, поэтому formfld1 приведет к NRE.

    Устранение

    Проверьте данные перед их использованием (также используйте параметры

    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)
    
    и SQL): ListBox1.SelectedItem

    Кроме того, вы можете использовать Nothing

    Формы Visual Basic

    ListBox1.SelectedItem.ToString

    Это довольно распространенный способ получить NRE. В C #, в зависимости от того, как он закодирован, среда IDE сообщит, что Option Strict не существует в текущем контексте или «не может ссылаться на нестатический элемент». Так что, в некоторой степени, это ситуация только для VB. Это также сложно, потому что это может привести к каскаду сбоев.

    Массивы и коллекции не могут быть инициализированы таким образом. Этот код инициализации будет выполняться до того, как конструктор создаст

    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
    
    или (ComboBox5.SelectedItem IsNot Nothing) AndAlso.... В результате:
    • Списки и коллекция просто будут пустыми
    • Массив будет содержать пять элементов Nothing
    • Назначение
      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
      
      приведет к немедленному NRE, поскольку у Nothing нет свойства Controls

    Ссылка на элементы массива позже приведет к NRE. Если вы сделаете это в Form, из-за странной ошибки среда IDE может не сообщить об исключительной ситуации, когда это произойдет. Исключение появится позже , когда ваш код попытается использоватьмассив. Это «тихое исключение» подробно описано в этом сообщении . Для наших целей ключевым моментом является то, что когда происходит что-то катастрофическое при создании формы (событие Controls или somevar), исключения могут не отображаться, код выходит из процедуры и просто отображает форму.

    Поскольку никакой другой код в вашем событии .Text или Form_Load не будет выполняться после NRE, множество других вещей нельзя оставлять неинициализированными.

    Sub New

    Примечание . Это относится ко всем без исключения ссылкам на элементы управления и компонентов, что делает их недопустимыми там, где они находятся:

    Form Load

    Частичное лекарство

    Любопытно, что VB не выдает предупреждение, но исправление состоит в том, чтобы объявить контейнеры на уровне формы, но инициализировать их в обработчике события загрузки формы, когда элементы управления do существуют. Это можно сделать в Sub New, если ваш код находится после вызова Form Load:

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

    Код массива еще может быть не в лесу. Любые элементы управления, которые находятся в элементе управления контейнера (например,

    Public Class Form1
    
        Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
        Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
        Private studentName As String = TextBox13.Text
    
    или Sub New) не будут найдены в InitializeComponent; они будут в коллекции Controls этой Panel или GroupBox. Также не будет возвращен элемент управления, если имя элемента управления написано с ошибкой (
    ' 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
    
    ). В таких случаях GroupBox будет снова сохранен в этих элементах массива, и при попытке обратиться к нему будет получено NRE.

    Их должно быть легко найти сейчас, когда вы знаете, что ищете: VS показывает ошибку ваших путей

    «Button2» находится на Panel

    Устранение

    Вместо косвенных ссылок по имени с использованием коллекции формы Me.Controls используйте контрольную ссылку:

    "TeStBox2"

    Функция ничего не возвращает

    Nothing

    Это тот случай, когда среда IDE предупредит вас, что « не все пути возвращают значение, и результатом может быть Panel ». Вы можете подавить предупреждение, заменив Controls на

    ' 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...})
    
    , но это не решит проблему. Все, что пытается использовать возврат, когда
    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
    
    приведет к NRE: NullReferenceException

    Устранение

    Замените Exit Function в функции на Return Nothing. Возврат пустого someCondition = False не совпадает с возвратом

    bList = myFoo.BarList()
    For Each b As Bar in bList      ' EXCEPTION
          ...
    
    . Если существует вероятность того, что возвращенный объект может быть проверен на 060035099/2001, то до 010035099/1111 будет возвращен р> Exit Function

    Плохо реализовано Try /Catch

    Плохо реализованный Try /Catch может скрыть, где проблема, и привести к новым:

    Return bList

    Это случай, когда объект создается не так, как ожидалось, но также демонстрирует полезность счетчика для пустого List.

    В SQL есть дополнительная запятая (после 'mailaddress'), что приводит к исключению в Nothing. После того, как Nothing ничего не делает,

     bList = myFoo.BarList()
     If bList IsNot Nothing Then...
    
    62 пытается выполнить очистку, но так как вы не можете 06003509911110010103505062 ноль 0600350506262505050 в SQL-коде, нулевой объект 060035050506250035050 не существует. новые результаты
    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
    
    .

    Пустой блок Catch - игровая площадка дьявола. Этот ОП был сбит с толку, почему он получил NRE в блоке .ExecuteReader. В других ситуациях пустой Catch может привести к чему-то гораздо более глубокому, идущему вниз по течению, и заставить вас тратить время на поиск неправильных вещей в неподходящем месте для решения проблемы. (Описанное выше «тихое исключение» обеспечивает то же развлекательное значение.)

    Устранение

    Не используйте пустые блоки Try /Catch - позвольте крушению кода, чтобы вы могли a) определить причину b) определить местоположение и c) применить надлежащее решение. Блоки Try /Catch не предназначены для сокрытия исключений от человека, обладающего уникальной квалификацией для их устранения - разработчика.

    DBNull - это не то же самое, что Nothing

    Finally

    Функция Close используется для проверки того, что значение равно DataReader: Из MSDN:

      

    Значение System.DBNull указывает, что объект представляет отсутствующие или несуществующие данные. DBNull - это не то же самое, что Nothing, что указывает на то, что переменная еще не инициализирована.

    Устранение

    NullReferenceException

    Как и раньше, вы можете проверить на Ничто, а затем для конкретного значения:

    Catch

    Пример 2

    Finally

    Catch возвращает первый элемент или значение по умолчанию, которое для справочных типов составляет

    For Each row As DataGridViewRow In dgvPlanning.Rows
        If Not IsDBNull(row.Cells(0).Value) Then
            ...
    
    , а не IsDBNull: System.DBNull

    Управление

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

    Если

    If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then
    
    с
    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), то Nothing будет пустым, и попытка ссылки на какое-либо свойство приведет к исключению.

    Устранение

    DBNull

    DataGridView

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

    If getFoo IsNot Nothing Then...
    

    Если

    Dim chk As CheckBox
    
    chk = CType(Me.Controls(chkName), CheckBox)
    If chk.Checked Then
        Return chk
    End If
    
    имеет CheckBox, он создает столбцы, но не называет их, поэтому приведенный выше код завершается ошибкой, когда он ссылается на них по имени.

    Устранение

    Назовите столбцы вручную или используйте указатель по индексу:

    chkName

    Пример 2. Остерегайтесь NewRow

    GroupBox

    Если для вашего chk задано значение

    If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...
    
    как
    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"
    
    (по умолчанию), все dgvBooks в пустой /новой строке внизу будут содержать AutoGenerateColumns = True. Большинство попыток использовать содержимое в 0600000000503503 (050), как правило, будут 061150, как например, 0 050 (например, 06). /р>

    Устранение

    Используйте цикл

    dgvBooks.Columns(0).Visible = True
    
    и проверьте свойство
    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
    
    , чтобы определить, является ли это последней строкой. Это работает независимо от того, является ли DataGridView истинным или нет: AllowUserToAddRows

    Если вы используете цикл True, измените счетчик строк или используйте Cells, если значение Nothing равно true.

    My.Settings (StringCollection)

    При определенных обстоятельствах попытка использовать элемент из ToString, который является For/Each, может привести к NullReference при первом его использовании. Решение то же самое, но не так очевидно. Рассмотрим:

    IsNewRow

    Поскольку VB управляет настройками для вас, разумно ожидать, что он инициализирует коллекцию. Это произойдет, но только если вы ранее добавили первоначальную запись в коллекцию (в редакторе настроек). Поскольку коллекция (по-видимому) инициализируется при добавлении элемента, она остается AllowUserToAddRows, если в редакторе настроек нет элементов для добавления.

    Устранение

    Инициализируйте коллекцию настроек в обработчике события

    For Each r As DataGridViewRow in myDGV.Rows
        If r.IsNewRow = False Then
             ' ok to use this row
    
    формы, если /когда это необходимо: For n

    Обычно коллекцию Exit For необходимо инициализировать только при первом запуске приложения. Альтернативное решение - добавить начальное значение в вашу коллекцию в Project - > Настройки | FooBars , сохраните проект, затем удалите поддельное значение.

    Ключевые моменты

    Возможно, вы забыли оператор IsNewRow.

    или р>

    То, что вы предположили, будет работать безупречно, чтобы вернуть инициализированный объект в ваш код, не так.

    Не игнорируйте предупреждения компилятора (всегда) и используйте My.Settings (всегда).

    Исключение MSDN NullReference р>     

    297
    2018-07-18 06: 31: 45Z

    Другой сценарий - это когда вы приводите пустой объект в тип значения . Например, код ниже:

    StringCollection

    Это бросит

    My.Settings.FooBars.Add("ziggy")         ' foobars is a string collection
    
    на бросок. Это кажется вполне очевидным в приведенном выше примере, но это может произойти в более сложных запоздалых сценариях, когда нулевой объект был возвращен из некоторого кода, который вам не принадлежит, и приведение, например, генерируется некоторой автоматической системой. р>

    Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления Calendar:

    Nothing

    Здесь Load фактически является свойством - типа

    If My.Settings.FooBars Is Nothing Then
        My.Settings.FooBars = New System.Collections.Specialized.StringCollection
    End If
    
    - типа Settings веб-элемента управления, и привязка может полностью возвратить что-либо значение NULL. Неявный ASP.NET Generator создаст кусок кода, который будет эквивалентен приведенному выше коду. И это вызовет New, который довольно трудно обнаружить, потому что он лежит в сгенерированном ASP.NET коде, который прекрасно компилируется ...     
    223
    2018-07-18 06: 28: 37Z
    1. Отличный улов. Однострочный способ избежать: Option Strict On
      2015-06-29 11: 07: 14Z

    Это означает, что рассматриваемая переменная ни на что не указана. Я мог бы сгенерировать это так:

    object o = null;
    DateTime d = (DateTime)o;
    

    Это вызовет ошибку, потому что, хотя я объявил переменную "NullReferenceException", она ни на что не указана. Когда я пытаюсь вызвать участника «

    <asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />
    
    », нет ссылки для его разрешения, и он выдаст ошибку.

    Чтобы избежать этой ошибки:

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

    Инструмент JetBrains Resharper определит каждое место в вашем коде, в котором может быть ошибка нулевой ссылки, что позволит вам поставить нулевую проверку. Эта ошибка - источник ошибок номер один, ИМХО.

        
    154
    2015-06-10 10: 01: 00Z
    1. Инструмент Resharper JetBrains определит каждое место в вашем коде, в котором может быть ошибка нулевой ссылки. Это неверно. У меня есть решение без этого обнаружения, но код иногда приводит к исключению. Я подозреваю, что это иногда необнаружимо - по крайней мере ими, - когда задействована многопоточность, но я не могу комментировать дальше, потому что я еще не определил местоположение моей ошибки.
      2018-01-21 07: 42: 30Z
    2. Но как решить эту проблему, когда возникает исключение NullReferenceException, используя HttpContext.Current.Responce.Clear (). Это не решается ни одним из вышеуказанных решений. потому что при создании объекта объекта HttpContext возникает ошибка «Не удалось разрешить перегрузку, потому что ни один из доступных« New »не принимает это количество аргументов.
      2018-02-02 11: 14: 26Z

    Это означает, что ваш код использовал переменную ссылки на объект, для которой было установлено значение null (то есть он не ссылался на фактический экземпляр объекта).

    Во избежание ошибки объекты, которые могут быть нулевыми, должны быть проверены на нулевое значение перед использованием.

    DateTime     
    150
    2014-07-28 19: 17: 10Z

    Помните, что независимо от сценария причина всегда одинакова в .NET:

      

    Вы пытаетесь использовать ссылочную переменную со значением Calendar/NullReferenceException. Если для ссылочной переменной задано значение DateTime x = (DateTime) o as DateTime? ?? defaultValue;/

    SqlConnection connection = null;
    connection.Open();
    
    , это означает, что в действительности она не содержит ссылку на экземпляр какого-либо объекта, существующего в куче.      

    Вы либо никогда не назначали что-либо переменной, ни разу не создавали экземпляр значения, назначенного переменной, либо устанавливали переменную равной connection/Open, либо вызывали функцию, для которой для переменной была установлена ​​переменная object == null/

    if (myvar != null)
    {
        // Go ahead and use myvar
        myvar.property = ...
    }
    else
    {
        // Whoops! myvar is null and cannot be used without first
        // assigning it to an instance reference
        // Attempting to use myvar here will result in NullReferenceException
    }
    
    для вы.
        
    94
    2015-06-10 10: 03: 19Z

    Пример этого исключения: когда вы пытаетесь что-то проверить, это пустое значение.

    Например:

    Nothing

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

    По сравнению с ArgumentNullException, который обычно генерируется как защитная мера, если метод ожидает, что то, что ему передается, не равно нулю.

    Больше информации в C # NullReferenceException и нулевой параметр .

        
    85
    2018-07-18 06: 32: 31Z

    Если вы не инициализировали ссылочный тип и хотите установить или прочитать одно из его свойств, он выдаст исключение NullReferenceException .

    Пример: р> null

    Вы можете просто избежать этого, проверив, не является ли переменная нулевой:

    Nothing

    Чтобы полностью понять, почему выбрасывается исключение NullReferenceException, важно знать разницу между типы значений и ссылочные типы .

    Итак, если вы имеете дело с типами значений , исключения NullReferenceExceptions могут не возникать. Хотя вам нужно соблюдать бдительность при работе с ссылочными типами !

    Только ссылочные типы, как следует из названия, могут содержать ссылки или указывать буквально на ничто (или «ноль»). Тогда как типы значений всегда содержат значение.

    Типы ссылок (они должны быть проверены):

    • динамический
    • объект литий>
    • строка

    Типы значений (вы можете просто игнорировать их):

    • Числовые типы
    • Интегральные типы
    • Типы с плавающей точкой
    • десятичное
    • BOOL
    • Пользовательские структуры
    81
    2018-07-18 06: 33: 04Z
    1. - 1: поскольку вопрос "Что такое исключение NullReferenceException", типы значений не имеют значения.
      2013-05-16 22: 00: 50Z
    2. @ Джон Сондерс: я не согласен. Как разработчику программного обеспечения очень важно уметь различать значения и ссылочные типы. в противном случае люди в конечном итоге проверят, являются ли целые числа нулевыми.
      2013-05-16 22: 28: 20Z
    3. Правда, только не в контексте этого вопроса.
      2013-05-16 22: 44: 05Z
    4. Спасибо за подсказку. Я немного улучшил его и добавил пример вверху. Я все еще думаю упомянуть ссылку & Типы значений полезны.
      2013-05-16 23: 02: 10Z
    5. Я думаю, что вы не добавили ничего, чего не было в других ответах, так как вопрос предполагает использование ссылочного типа.
      2013-05-18 23: 24: 59Z

    Другим случаем, когда может произойти null, является (неправильное) использование оператор Nothing :

    null

    Здесь Nothing и null являются несовместимыми типами;

    string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)
    
    if (testString.Length == 0) // Throws a nullreferenceexception
    {
        //Do something
    } 
    
    не может быть преобразован /приведен к
    Person p = null;
    p.Name = "Harry"; // NullReferenceException occurs here.
    
    . При сбое этого приведения
    Person p = null;
    if (p!=null)
    {
        p.Name = "Harry"; // Not going to run to this point
    }
    
    возвращает NullReferenceExceptions. Использование as после этого вызывает
    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
    
    .

    Как правило, вы должны использовать приведение или Book следующим образом:

    Если вы ожидаете, что преобразование типов будет всегда успешным (т. е. вы знаете, какой объект должен быть раньше времени), то вам следует использовать приведение:

    Car

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

    Book     
    75
    2018-07-18 06: 33: 28Z
    1. Это может случиться много, когда распаковываете переменную. Я нахожу, что это часто случается в обработчиках событий после того, как я изменил тип элемента пользовательского интерфейса, но забыл обновить код.
      2014-02-19 00: 24: 28Z

    Вы используете объект, который содержит ссылку на нулевое значение. Так что это дает нулевое исключение. В этом примере строковое значение равно нулю, и при проверке его длины произошло исключение.

    Пример: р> as

    Ошибка исключения:

      

    Необработанное исключение:

         

    System.NullReferenceException: ссылка на объект не установлена ​​на экземпляр   объекта. в Program.Main ()

        
    63
    2015-05-25 13: 41: 20Z
    1. Как глубоко! Я никогда не считал нулевую константу эталонным значением. Так вот как C # абстрагирует NullPointer? B /c, как я помню в C ++, NPE может быть вызван разыменованием неинициализированного указателя (т. Е. Ref ref в c #), значением по умолчанию которого является адрес, который не выделен этому процессу (во многих случаях это будет 0, особенно в более поздних версиях C ++, которые делали автоинициализацию, которая принадлежит ОС - f вместе с ней и die beeotch (или просто поймайте сигил, с помощью которого ОС атакует ваш процесс)).
      2013-07-31 18: 55: 50Z

    Хотя что вызывает NullReferenceExceptions и подходы к избежать /исправить такого исключения были рассмотрены в других ответах, что многие программисты еще не узнали, как самостоятельно отладить такие исключения во время разработки.

    В Visual Studio это обычно легко благодаря отладчику Visual Studio . р>

    Во-первых, убедитесь, что будет обнаружена правильная ошибка - см. Как разрешить взлом «System.NullReferenceException» в VS2010? Примечание 1

    Тогда либо Начните с отладки (F5) или Подключите [VS Debugger] к запущенному процессу . Иногда может быть полезно использовать null , который предложит запустить отладчик.

    Теперь, когда выбрасывается (или не обрабатывается) исключение NullReferenceException, отладчик останавливается (помните, как установлено выше?) на строке, в которой произошло исключение. Иногда ошибку легко обнаружить.

    Например, в следующей строке единственный код, который может вызвать исключение, - это если значение mybook равно нулю. Это можно проверить, посмотрев в окно просмотра или запустите выражения в окне немедленного использования .

    NullReferenceException

    В более сложных случаях, таких как следующие, вам нужно использовать один из описанных выше методов (Watch или Immediate Windows), чтобы проверить выражения, чтобы определить, было ли значение as нулевым или

    ComicBook cb = (ComicBook)specificBook;
    
    равно нулю. as

    Когда где исключение является throw, было найдено, обычно тривиально рассуждать в обратном направлении, чтобы выяснить, где было введено нулевое значение -

    Потратьте время, необходимое для понимания причины исключения. Осмотрите для нулевых выражений. Проверьте предыдущие выражения, которые могли привести к таким нулевым выражениям. Добавьте точки останова и пошагово пройдитесь по программе. Используйте отладчик.

    1 Если Break on Throws слишком агрессивен иОтладчик останавливается на NPE в .NET или сторонней библиотеке, Перерыв на User- Необработанный может быть использован для ограничения обнаруженных исключений. Кроме того, VS2012 представляет Just My Code , который я также рекомендую включить.

      

    Если вы выполняете отладку с включенным Just My Code, поведение будет немного другим. При включенном Just My Code отладчик игнорирует исключительные ситуации общеязыковой среды выполнения (CLR), которые генерируются вне My Code и не проходят через My Code

        
    59
    2018-07-18 06: 42: 11Z

    Саймон Мурье привел этот пример :

    ComicBook cb = specificBook as ComicBook;
    if (cb != null) {
       // ...
    }
    

    где распаковка (преобразование) из

    string value = null;
    if (value.Length == 0) // <-- Causes exception
    {
        Console.WriteLine(value); // <-- Never reached
    }
    
    (или из одного из классов Debugger.Break или myString или из типа интерфейса) to тип значения (отличный от
    var x = myString.Trim();
    
    ) сам по себе дает str1.

    В другом направлении бокс преобразовал из в str2, который имеет

    var x = str1.Trim() + str2.Trim();
    
    , равный
    object o = null;
    DateTime d = (DateTime)o;  // NullReferenceException
    
    в а ссылочный тип, может дать ссылку object, которая впоследствии может привести к System.ValueType. Классический пример: System.Enum

    Иногда бокс происходит по-другому. Например, с помощью этого неуниверсального метода расширения:

    Nullable<>

    следующий код будет проблематичным:

    NullReferenceException

    Эти случаи возникают из-за особых правил, которые среда выполнения использует при упаковке экземпляров Nullable<>.

        
    55
    2018-07-18 06: 34: 19Z

    Добавление случая, когда имя класса для сущности, используемой в каркасе сущностей, совпадает с именем класса для файла кода веб-формы.

    Предположим, у вас есть веб-форма Contact.aspx, класс codebehind которой - Contact, и у вас есть имя сущности Contact.

    Тогда следующий код вызовет исключение NullReferenceException при вызове context.SaveChanges ()

    HasValue

    Ради полноты класса DataContext

    false

    и класс сущности Contact. Иногда классы сущностей являются частичными классами, так что вы можете расширять их и в других файлах.

    null

    Ошибка возникает, когда сущность и класс codebehind находятся в одном пространстве имен. Чтобы это исправить, переименуйте класс сущности или класс codebehind для Contact.aspx.

    Причина Я до сих пор не уверен в причине. Но всякий раз, когда какой-либо из классов сущностей расширяет System.Web.UI.Page, эта ошибка возникает.

    Для обсуждения взгляните на NullReferenceException в DbContext.saveChanges ()

        
    40
    2017-05-23 12: 34: 45Z

    Еще один общий случай, когда можно получить это исключение, связан с классами насмешек во время модульного тестирования. Независимо от используемой среды моделирования, вы должны убедиться, что все соответствующие уровни иерархии классов должным образом смоделированы. В частности, все свойства NullReferenceException, на которые ссылается тестируемый код, должны быть проверены.

    См. " NullReferenceException, возникающее при тестировании пользовательского атрибута AuthorizationAttribute ", для более подробного описания. пример. р>     

    39
    2017-05-23 12: 34: 45Z

    У меня другой взгляд на этот вопрос. Такого рода ответы ", что еще я могу сделать, чтобы избежать этого? "

    При работе на разных уровнях , например, в приложении MVC, контроллеру нужны сервисы для вызова бизнес-операций. В таких сценариях Контейнер внедрения зависимостей можно использовать для инициализации служб, чтобы избежать NullReferenceException . Таким образом, это означает, что вам не нужно беспокоиться о проверке на null и просто вызывать сервисы из контроллера, как если бы они всегда были доступны (и инициализированы) как одиночный или прототип.

    DateTime? d = null;
    var s = d.ToString();  // OK, no exception (no boxing), returns ""
    var t = d.GetType();   // Bang! d is boxed, NullReferenceException
    
        
    38
    2016-12-29 08: 44: 58Z
    1. - 1: это обрабатывает только один сценарий - сценарий неинициализированных зависимостей. Это сценарий меньшинства для исключения NullReferenceException. В большинстве случаев это просто неправильное понимание того, как работают объекты. Следующими наиболее частыми являются другие ситуации, когда разработчик предполагал, что объект будет инициализирован автоматически.
      2014-03-07 00: 06: 17Z
    2. Все остальные уже получили ответы выше.
      2014-03-07 00: 23: 32Z
    3. Внедрение зависимостей обычно не используется во избежание исключения NullReferenceException. Я не верю, что вы нашли общий сценарий здесь. В любом случае, если вы отредактируете свой ответ, чтобы он соответствовал стилю stackoverflow.com/a/15232518/76337 , тогда я уберу понижение.
      2014-03-07 00: 30: 09Z

    На вопрос «что мне с этим делать» может быть много ответов.

    Более "формальным" способом предотвращения возникновения таких ошибок при разработке является применение дизайн по контракту в вашем коде. Это означает, что вы должны установить класс инварианты и /или даже функцию /метод предварительные условия и постусловия в вашей системе во время разработки.

    Короче говоря, инварианты класса гарантируют, что в вашем классе будут некоторые ограничения, которые не будут нарушаться при обычном использовании (и, следовательно, класс не попадет в противоречивое состояние). Предварительные условия означают, что данные, переданные в качестве входных данных для функции /метода, должны соответствовать некоторым установленным ограничениям и никогда их нарушать, а постусловия означают, что функция /вывод метода должен снова следовать установленным ограничениям, не нарушая их. Условия контракта не должны никогда нарушаться во время выполнения безошибочной программы, поэтому проектирование по контракту проверяется на практике в режиме отладки, в то время как отключается в выпусках , чтобы максимизировать развитая производительность системы.

    Таким образом, вы можете избежать

    public static void MyExtension(this object x)
    {
      x.ToString();
    }
    
    случаев, которые являются результатом нарушения установленных ограничений. Например, если вы используете свойство объекта
    DateTime? d = null;
    d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.
    
    в классе и позже попытаетесь вызвать один из его методов, а Nullable<> имеет нулевое значение, то это приведет к
    Contact contact = new Contact { Name = "Abhinav"};
    var context = new DataContext();
    context.Contacts.Add(contact);
    context.SaveChanges(); // NullReferenceException at this line
    
    :
    public class DataContext : DbContext 
    {
        public DbSet<Contact> Contacts {get; set;}
    }
    

    Но если вы установите «свойство X никогда не должно иметь нулевое значение» в качестве предварительного условия метода, то вы можете предотвратить сценарий, описанный ранее:

    public partial class Contact 
    {
        public string Name {get; set;}
    }
    

    По этой причине код Контракты существуют для приложений .NET.

    Кроме того, проектирование по контракту может быть применено с использованием утверждений .

    ОБНОВЛЕНИЕ . Стоит отметить, что этот термин был придуман Бертраном Мейером в связи с его дизайном языка программирования Eiffel .

        
    37
    2016-12-30 15: 56: 42Z
    1. Я подумал добавить это, поскольку никто не упомянул об этом, и, поскольку он существует в качестве подхода, я намеревался обогатить тему.
      2014-12-26 01: 03: 01Z
    2. Спасибо за обогащение темы. Я дал свое мнение о вашем дополнении. Теперь другие могут сделать то же самое.
      2014-12-26 01: 05: 44Z
    3. Я подумал, что это достойное дополнение к теме, поскольку это очень популярная тема. Я уже слышал о контрактах кода, и это было хорошим напоминанием об их использовании.
      2015-01-08 02: 03: 57Z

    HttpContext генерируется, когда мы пытаемся получить доступ к свойствам нулевого объекта или когда строковое значение становится пустым, и мы пытаемся получить доступ к строковым методам.

    Например:

    1. При обращении к строковому методу пустой строки:

      public class MyController
      {
          private ServiceA serviceA;
          private ServiceB serviceB;
      
          public MyController(ServiceA serviceA, ServiceB serviceB)
          {
              this.serviceA = serviceA;
              this.serviceB = serviceB;
          }
      
          public void MyMethod()
          {
              // We don't need to check null because the dependency injection container 
              // injects it, provided you took care of bootstrapping it.
              var someObject = serviceA.DoThis();
          }
      }
      
    2. При обращении к свойству нулевого объекта:

      NullReferenceException
    34
    2015-06-10 06: 04: 10Z
    1. Это неверно. X не вызовет исключение нулевой ссылки. Он представляет собой фактическую строку, хотя и пустую (т.е. X). Поскольку здесь есть объект для вызова NullReferenceException, нет смысла выдавать исключение нулевой ссылки.
      2015-07-24 06: 00: 35Z

    TL; DR: попробуйте использовать

    public X { get; set; }
    
    public void InvokeX()
    {
        X.DoSomething(); // if X value is null, you will get a NullReferenceException
    }
    
    вместо
    //Using code contracts:
    [ContractInvariantMethod]
    protected void ObjectInvariant () 
    {
        Contract.Invariant ( X != null );
        //...
    }
    

    Я получал NullReferenceException, когда пытался отобразить представление в представлении, отправив ему модель, например так:

    string str = string.Empty;
    str.ToLower(); // throw null reference exception
    

    Отладка показала, что модель была нулевой внутри MyOtherView. Пока я не изменил его на:

    Public Class Person {
        public string Name { get; set; }
    }
    Person objPerson;
    objPerson.Name  /// throw Null refernce Exception 
    

    И это сработало.

    Кроме того, причина, по которой у меня не было String.Empty.ToLower() для начала, заключалась в том, что Visual Studio иногда выбрасывает выглядящие из-за ошибки волнистые линии в "", если он находится внутри цикла ToLower(), построенного по-другому, даже если это не совсем так. ошибка:

    Html.Partial

    Но я смог без проблем запустить приложение с этой «ошибкой». Мне удалось избавиться от ошибки, изменив структуру цикла Renderpage так:

    Object reference not set to an instance of an object

    Хотя у меня такое чувство, что это произошло из-за того, что Visual Studio неправильно читал амперсанды и скобки.

        
    30
    2016-05-16 08: 35: 52Z
    1. Вы хотели
      @{
          MyEntity M = new MyEntity();
      }
      @RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null
      
      , а не
      @{
          MyEntity M = new MyEntity();
      }
      @Html.Partial("_MyOtherView.cshtml", M);
      
      2015-07-24 13: 55: 45Z
    2. Кроме того, укажите, какая строка вызвала исключение и почему.
      2015-07-24 13: 56: 53Z
    3. Ошибка произошла в MyOtherView.cshtml, который я здесь не включил, потому что Модель не отправлялась должным образом (это было Html.Partial), поэтому я знал об ошибке было с тем, как я отправлял модель.
      2015-07-27 11: 44: 53Z

    Что вы можете с этим поделать?

    Здесь есть много хороших ответов, объясняющих, что такое пустая ссылка и как ее отладить. Но есть очень мало о том, как предотвратить проблему или, по крайней мере, облегчить ее обнаружение.

    Проверьте аргументы

    Например, методы могут проверять различные аргументы, чтобы определить, являются ли они пустыми, и выдавать Html.Partial, исключение, явно созданное для этой конкретной цели.

    Конструктор для foreach даже принимает имя параметра и сообщение в качестве аргумента, чтобы вы могли сообщить разработчикуименно в чем проблема.

    @inherits System.Web.Mvc.WebViewPage
    @{
        ViewBag.Title = "Entity Index";
        List<MyEntity> MyEntities = new List<MyEntity>();
        MyEntities.Add(new MyEntity());
        MyEntities.Add(new MyEntity());
        MyEntities.Add(new MyEntity());
    }
    <div>
        @{
            foreach(var M in MyEntities)
            {
                // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
                @Html.Partial("MyOtherView.cshtml");
            }
        }
    </div>
    

    Используйте инструменты

    Есть также несколько библиотек, которые могут помочь. Например, «Resharper» может выдавать вам предупреждения во время написания кода, особенно если вы используете их атрибут: NotNullAttribute

    Есть «Microsoft Code Contracts», где вы используете синтаксис, такой как foreach, который дает вам время выполнения и проверку компиляции: Представляем кодовые контракты .

    Существует также «PostSharp», который позволит вам просто использовать такие атрибуты:

    @foreach(var M in MyEntities){
        ...
    }
    

    Сделав это и сделав PostSharp частью вашего процесса сборки, Html.Partial будет проверен на нулевое значение во время выполнения. См. нулевую проверку PostSharp р>

    Решение с использованием простого кода

    Или вы всегда можете написать собственный подход, используя старый код. Например, вот структура, которую вы можете использовать для перехвата нулевых ссылок. Он смоделирован по той же концепции, что и @Html.Partial:

    Null

    Вы будете использовать очень похоже на то же самое, что вы использовали бы ArgumentNullException, за исключением того, что с целью добиться прямо противоположного - запретить ArgumentNullException. Вот несколько примеров:

    public void DoSomething(MyObject obj) {
        if(obj == null) 
        {
            throw new ArgumentNullException("obj", "Need a reference to obj.");
        }
    }
    

    Contract.Requires(obj != null) неявно приводится к

    public void DoSometing([NotNull] obj)
    
    и обратно, поэтому вы можете использовать его практически везде, где вам это нужно. Например, вы можете передать объект obj методу, который принимает Nullable<T>:
    [System.Diagnostics.DebuggerNonUserCode]
    public struct NotNull<T> where T: class
    {
        private T _value;
    
        public T Value
        {
            get
            {
                if (_value == null)
                {
                    throw new Exception("null value not allowed");
                }
    
                return _value;
            }
            set
            {
                if (value == null)
                {
                    throw new Exception("null value not allowed.");
                }
    
                _value = value;
            }
        }
    
        public static implicit operator T(NotNull<T> notNullValue)
        {
            return notNullValue.Value;
        }
    
        public static implicit operator NotNull<T>(T value)
        {
            return new NotNull<T> { Value = value };
        }
    }
    

    Как вы можете видеть выше, как и для nullable, вы получите доступ к базовому значению через свойство Nullable<T>. Кроме того, вы можете использовать явное или неявное приведение, вы можете увидеть пример с возвращаемым значением ниже:

    null

    Или вы даже можете использовать его, когда метод просто возвращает

    NotNull<Person> person = null; // throws exception
    NotNull<Person> person = new Person(); // OK
    NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null
    
    (в данном случае NotNull<T>), выполняя приведение. Например, следующий код будет соответствовать приведенному выше коду: T

    Объединить с расширением

    Объедините Person с методом расширения, и вы сможете охватить еще больше ситуаций. Вот пример того, как может выглядеть метод расширения:

    NotNull<Person>

    А вот пример того, как его можно использовать:

    Person person = new Person { Name = "John" };
    WriteName(person);
    
    public static void WriteName(NotNull<Person> person)
    {
        Console.WriteLine(person.Value.Name);
    }
    

    GitHub р>

    Для справки, я сделал приведенный выше код доступным на GitHub, вы можете найти его по адресу:

    https://github.com/luisperezphd/NotNull

    Функция родственного языка

    В C # 6.0 появился «нулевой условный оператор», который немного помогает в этом. С помощью этой функции вы можете ссылаться на вложенные объекты, и если какой-либо из них будет Value, все выражение вернет

    Person person = GetPerson();
    
    public static NotNull<Person> GetPerson()
    {
        return new Person { Name = "John" };
    }
    
    .

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

    T

    Представьте, что Person - это объект типа

    Person person = (NotNull<Person>)GetPerson();
    
    public static Person GetPerson()
    {
        return new Person { Name = "John" };
    }
    
    , который имеет свойство с именем NotNull<T> и так далее. Если
    [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;
        }
    }
    
    ,
    var person = GetPerson().NotNull();
    
    , null или null равен
    var address = country?.State?.County?.City;
    
    , то country111100101035062111100101035062_0000015062

    Это отличная функция, но она дает вам меньше информации. Это не делает очевидным, какой из 4 является нулевым.

    Встроенный как Nullable?

    В C # есть хорошая сокращенная запись Country, вы можете сделать что-нибудь обнуляемое, поставив знак вопроса после такого типа, как State.

    Было бы неплохо, если бы C # имел что-то вроде структуры country выше и имел похожую стенографию, может быть, восклицательный знак (!), чтобы вы могли написать что-то вроде: State.

        
    22
    2017-10-29 09: 06: 44Z
    1. Никогда не выбрасывайте NullReferenceException
      2016-03-06 20: 35: 21Z
    2. @ JohnSaunders осмелился спросить, почему? (Серьезно, хотя почему?)
      2016-03-07 15: 29: 30Z
    3. NullReferenceException предназначено для создания CLR. Это означает, что ссылка на ноль произошла. Это не означает, что ссылка на ноль будет иметь место, за исключением того, что вы сначала хитро проверили.
      2016-03-07 15: 43: 52Z
    4. Я понимаю вашу точку зрения о том, как это может сбить с толку. Я обновил его до обычного исключения для этого примера и пользовательского исключения в GitHub.
      2016-03-07 18: 41: 52Z
    5. Отличный ответ на такой простой вопрос. Это не так плохо, когда ваш код не работает. Это ужасно, когда он приходит из какой-то коммерческой сторонней библиотеки, на которую вы полагаетесь, и служба поддержки клиентов настаивает на том, что именно ваш код вызывает проблему. И вы не совсем уверены, что это не так, и весь проект может быть остановлен. Я действительно думаю, что это может сделать подходящую эпитафию для моего надгробия: «Ссылка на объект не установлена ​​на экземпляр объекта».
      2016-05-03 04: 01: 06Z

    Вы можете исправить NullReferenceException чистым способом с помощью Null-условных операторов в c # 6 и написать меньше кода для обработки нулевых проверок.

    Используется для проверки на нулевое значение перед выполнением операции доступа к члену (?.) или индекса (? [).

    Пример р> County

    эквивалентно:

    City

    В результате имя будет нулевым, если p равно нулю или когда p.Spouse равно нулю.

    В противном случае имени переменной будет присвоено значение p.Spouse.FirstName.

    Подробнее: Null- условные операторы

        
    9
    2017-11-29 23: 19: 36Z

    Строка ошибки "Ссылка на объект не установлена ​​для экземпляра объекта. "утверждает, что вы не назначили объект экземпляра для ссылки на объект, и все же вы получаете доступ к свойствам /методам этого объекта.

    Например: допустим, у вас есть класс с именем myClass, и он содержит одно свойство prop1.

    null

    Теперь вы получаете доступ к этому prop1 в каком-то другом классе, как показано ниже:

    address will be

    строка выше выдает ошибку, потому что ссылка на класс myClass объявлена, но не создана, или экземпляр объекта не назначен для ссылки на этот класс.

    Чтобы это исправить, нужно создать экземпляр (назначить объект для ссылки на этот класс).

    . Therefore you only have to check whether     
    8
    2017-03-08 10: 58: 18Z
    1. На этот ответ уже был дан ответ.
      2017-03-08 11: 31: 26Z

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

    Пограничный вариант № 1: одновременный доступ к словарю

    Общие словари в .NET не являются поточно-ориентированными, и они иногда могут выдавать is или даже (чаще) Nullable<T> при попытке доступа к ключу из двух параллельных потоков. В этом случае исключение вводит в заблуждение.

    Edge case # 2: небезопасный код

    Если int? генерируется кодом NotNull<T>, вы можете просмотреть переменные-указатели и проверить их на public void WriteName(Person! person) или что-то еще. Это то же самое («исключение нулевого указателя»), но в небезопасном коде переменные часто приводятся к типам значений /массивам и т. Д., И вы бьетесь головой о стену, задаваясь вопросом, как тип значения может бросить это исключение.

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

        
    8
    2017-04-19 00: 08: 28Z
  5. Ваш пример словаря не является крайним случаем. Если объект не является потокобезопасным, то использование его из нескольких потоков приводит к случайным результатам. Ваш пример небезопасного кода чем-то отличается от
      var name = p?.Spouse?.FirstName;
    
    ?
    2017-03-24 02: 03: 11Z

NullReferenceException или ссылка на объект, не установленная для экземпляра объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создан. Например:

Предположим, у вас есть класс с именем Student.

    if (p != null)
    {
        if (p.Spouse != null)
        {
            name = p.Spouse.FirstName;
        }
    }

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public Class myClass
{
   public int prop1 {get;set;}
}

Как видно из приведенного выше кода, утверждение Student s - объявляет только переменную типа Student. Обратите внимание, что на этом этапе класс Student не создается. Следовательно, когда оператор s.GetFullName () выполняется, он генерирует исключение NullReferenceException.

    
3
2016-07-28 10: 52: 34Z

Ну, простыми словами:

Вы пытаетесь получить доступ к объекту, который не создан или в данный момент отсутствует в памяти.

Так как с этим справиться?

  1. Отладьте и дайте отладчику сломаться ... Он напрямую приведет вас к сломанной переменной ... Теперь ваша задача просто исправить это .. Используя ключевое слово new в соответствующем месте.

  2. Если это вызвано некоторыми командами database из-за того, что объект отсутствует, то все, что вам нужно сделать, - это выполнить нулевую проверку и обработать ее:

    public class Demo
    {
         public void testMethod()
         {
            myClass ref = null;
            ref.prop1 = 1;  //This line throws error
         }
    }
    
  3. Самый сложный ... если GC уже собрал объект ... Обычно это происходит, если вы пытаетесь найти объект, используя строки ... То есть, находя его по имени объекта, может случиться так, что сборщик мусора уже очистил его. .. Это трудно найти, и это станет большой проблемой ... Лучший способ решить эту проблему - делать нулевые проверки везде, где это необходимо в процессе разработки. Это сэкономит вам много времени.

Под поиском по имени я подразумеваю, что некоторые фреймворки позволяют вам FIndObject, используя строки, и код может выглядеть следующим образом: FindObject ("ObjectName");

    
2
2016-05-16 08: 34: 08Z
  1. Если у вас есть ссылка на объект, GC никогда не очищает его
    2015-12-24 07: 51: 46Z
  2. если вы используете такие вещи, как FindObject ("Имя объекта"), GC никогда не узнает заранее, что вы собираетесь ссылаться на этот объект ... вот что пытался объяснить .. это происходит во время выполнения
    2015-12-24 08: 11: 04Z
  3. Существуют некоторые платформы, обеспечивающие эту функциональность в C #, такие как Unity. вопрос не имеет ничего общего с BCl. Прежде чем критиковать, поищите в интернете множество функций, подобных им, и для доброй информации я даже использую ее ежедневно. Теперь, пожалуйста, скажите мне, как ответ не имеет смысла.
    2015-12-24 12: 35: 24Z
  4. документы .unity3d.com /ScriptReference /… проверьте ссылку и исправьте себя. mr.expert: p
    2015-12-24 12: 54: 12Z
  5. Примеры, которые я видел в вашей ссылке, присваивают результаты GameObject.Find полю участника. Это ссылка, и сборщик мусора не будет собирать ее, пока не будет собран содержащий объект.
    2016-05-25 18: 00: 40Z

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

Пример:

public class Demo
{
     public void testMethod()
     {
        myClass ref = null;
        ref = new myClass();
        ref.prop1 = 1;  
     }
}

здесь, если адрес равен нулю, вы получите исключение NullReferenceException.

Таким образом, на практике мы всегда должны использовать проверку на нуль, прежде чем обращаться к свойствам в таких объектах (особенно в универсальных)

NullReference     
0
2017-08-24 05: 55: 22Z
  1. На этот вопрос уже отвечали несколько раз.
    2017-08-26 03: 24: 14Z

Буквально самый простой способ исправить NullReferenceExeption имеет два способа. Если у вас есть GameObject, например, с прикрепленным скриптом и переменной с именем rb (hardbody), эта переменная будет начинаться с нуля при запуске вашей игры.
Вот почему вы получаете NullReferenceExeption, потому что на компьютере нет данных, хранящихся в этой переменной.

Я буду использовать переменную RigidBody в качестве примера.
Мы можем действительно легко добавить данные несколькими способами:

  1. Добавьте RigidBody к своему объекту с помощью AddComponent > Физика > Rigidbody
    Затем перейдите в свой сценарий и введите KeyNotFoundException
    Эта строка кода лучше всего работает под вашими NullReferenceException или unsafe функциями.
  2. Вы можете добавить компонент программно и назначить переменную одновременно с помощью одной строки кода: IntPtr.Zero

Дополнительные примечания. Если вы хотите, чтобы функция Unity добавила компонент к вашему объекту, и вы, возможно, забыли добавить его, вы можете ввести null над объявлением класса (пробел под всеми вашими использованиями).
Наслаждайтесь игрой и получайте удовольствие!

    
0
2017-11-14 20: 45: 02Z

Если вы получаете это сообщение во время сохранения или компиляции сборки, просто закройте все файлы, а затем откройте любой файл для компиляции и сохранения.

Для меня причина была в том, что я переименовал файл, а старый файл все еще был открыт.

    
- 1
2017-10-14 18: 48: 08Z

Чтобы использовать методы и член объекта, сначала необходимо создать этот объект. Если вы не создали его (переменная, которая должна содержать объект, не инициализирована), но вы пытаетесь использовать его методы или переменные, вы получите эту ошибку.

Иногда вы можете просто забыть выполнить инициализацию.

Отредактировано: new не может вернуть значение NULL, но возникает исключение при сбое. Давным-давно это было в некоторых языках, но не больше. Спасибо @Джон Сондерс за то, что указал на это.

    
- 1
2017-10-27 13: 56: 19Z
  1. public class Student
    {
        private string FirstName;
        private string LastName;
        public string GetFullName()
        {
            return FirstName + LastName;
        }
    }
    
    никогда не возвращает ноль
    2017-10-27 13: 00: 04Z

Это, в основном, исключительная ссылка Null . Как Microsoft заявляет-

  

Исключение NullReferenceException выдается при попытке доступа к   член типа с нулевым значением.

Что это значит?

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

«Эй, подождите, у этого члена нет значений, поэтому он не может выполнить задачу, которую вы передаете ему».

Само исключение говорит, что что-то ссылаетсяошибся, но значение которого не установлено. Таким образом, это означает, что это происходит только при использовании ссылочных типов, поскольку типы значений не могут быть обнуляемыми.

NullReferenceException не возникнет, если мы используем члены типа Value.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Приведенный выше код показывает простую строку, которой присваивается значение null .

Теперь, когда я пытаюсь напечатать длину строки str , я получаю сообщение о необработанном исключении типа 'System.NullReferenceException' , потому что член str указывает на ноль, и ноль не может быть длиной.

strong NullReferenceException ’также возникает, когда мы забываем создать экземпляр ссылочного типа.

Предположим, у меня есть класс и метод-член. Я не создал экземпляр своего класса, а только назвал свой класс. Теперь, если я попытаюсь использовать метод, компилятор выдаст ошибку или выдаст предупреждение (в зависимости от компилятора).

if (i == null) {
    // Handle this
}

Компилятор для приведенного выше кода вызывает ошибку, что переменная obj не назначена, что означает, что наша переменная имеет нулевые значения или ничего. Компилятор для приведенного выше кода вызывает ошибку, что переменная obj не назначена, что означает, что наша переменная имеет нулевые значения или ничего.

Почему это происходит?

  • NullReferenceException возникает из-за нашей ошибки в том, что мы не проверили значение объекта. Мы часто оставляем значения объектов непроверенными в разработке кода.

  • Это также возникает, когда мы забываем создавать экземпляры наших объектов. Использование методов, свойств, коллекций и т. Д., Которые могут возвращать или устанавливать значения NULL, также может быть причиной этого исключения.

Как этого можно избежать?

Существуют различные способы и способы избежать этого известного исключения:

  1. Явная проверка. Мы должны придерживаться традиции проверки объектов, свойств, методов, массивов и коллекций на наличие нулевых значений. Это может быть просто реализовано с помощью условных операторов, таких как if-else, if-else и т. Д.

  2. Обработка исключений: один из важных способов управления этим исключением. Используя простые блоки try-catch-finally, мы можем контролировать это исключение, а также вести его журнал. Это может быть очень полезно, когда ваше приложение находится на стадии разработки.

  3. Нулевые операторы: Нулевой оператор объединения и нулевые условные операторы также могут быть полезны при установке значений для объектов, переменных, свойств и полей.

  4. Отладчик. Для разработчиков у нас есть большое оружие отладки. Если мы столкнулись с NullReferenceException во время разработки, мы можем использовать отладчик, чтобы добраться до источника исключения.

  5. Встроенный метод: системные методы, такие как GetValueOrDefault (), IsNullOrWhiteSpace () и IsNullorEmpty (), проверяют наличие нулей и присваивают значение по умолчанию, если есть нулевое значение.

Здесь уже есть много хороших ответов. Вы также можете проверить более подробное описание с примерами на моем блог .

Надеюсь, это тоже поможет!

    
- 2
2017-10-18 07: 31: 02Z
  1. Вы в основном скопировали половину этого сообщения в блоге и не добавили ничего нового, к которому не относятся существующие ответы.
    2017-07-18 14: 41: 29Z
  2. @ codecaster Сказано ли это копирование, когда вы переписываете резюме из своего собственного блога. Я знаю, что в моем ответе нет ничего нового и ничего нового, чего нет в предыдущих ответах, но я хочу внести свой вклад более изощренно и позволить другим понять то, как я понял. Будем рады, даже если это поможет одному человеку. Добросовестно.
    2017-07-18 18: 01: 29Z

Возможен сценарий, связанный с классом . Вопрос закончил тем, что был закрыт до того, как я сформулировал решение: https://stackoverflow.com/questions/43348009/unable-to-instantiate-class

Остерегайтесь классов, не являющихся экземплярами: Если какая-либо часть вашего конструктора в классе выбрасывает

string postalcode=Customer.Address.PostalCode; 
//if customer or address is null , this will through exeption
, то класс не создается. В моем случае он пытался получить строку подключения из файла web.config, которого не было.

Я создал экземпляр класса:

string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception

Внутри самого класса был вызов для получения строки соединения из rb = GetComponent<Rigidbody>();. Эта часть конструктора вызвала исключение нулевого значения, поэтому Start() было нулевым.

Если вы когда-либо сталкивались с ситуацией, когда класс не создается, попробуйте убедиться, что ни одна часть конструктора класса не выбрасывает Awake(). F-11, и переберите класс и убедитесь, что в нем нет нулей.

    
- 5
2017-05-23 10: 31: 36Z
  1. Конструкторы никогда не возвращают ноль. Они либо создают экземпляр объекта, либо выдают исключение.
    2017-04-11 21: 12: 13Z
  2. @ CodeCaster Я перефразировал весь ответ, надеясь удовлетворить ваши опасения. Дело в том, что я не видел в других ответах, что если какая-либо часть конструктора класса выдает исключение, это приведет к тому, что класс не будет создан. Хотя это имеет большой смысл для меня, это не стало для меня очевидным выбором.
    2017-04-12 16: 13: 26Z
  3. Опять же, это не может произойти. Если этот конструктор выбрасывает, следующая строка не будет выполнена.
    2017-04-13 05: 32: 54Z
  4. @ logixologist Полностью согласен с CC здесь, этот ответ не имеет никакого смысла в его нынешнем виде.
    2017-07-05 12: 36: 38Z
rb = AddComponent<RigidBody>();
источник размещен Вот