Прочитать на английском

Поделиться через


NullReferenceException Класс

Определение

Исключение, возникающее при попытке разыменования указателя NULL на объект.

C#
public class NullReferenceException : Exception
C#
public class NullReferenceException : SystemException
C#
[System.Serializable]
public class NullReferenceException : SystemException
C#
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class NullReferenceException : SystemException
Наследование
NullReferenceException
Наследование
NullReferenceException
Атрибуты

Комментарии

Исключение NullReferenceException возникает при попытке получить доступ к члену для типа со значением null. Исключение NullReferenceException обычно отражает ошибку разработчика и возникает в следующих сценариях:

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

    C#
    using System;
    using System.Collections.Generic;
    
    public class Example
    {
       public static void Main(string[] args)
       {
          int value = Int32.Parse(args[0]);
          List<String> names;
          if (value > 0)
             names = new List<String>();
    
          names.Add("Major Major Major");
       }
    }
    // Compilation displays a warning like the following:
    //    Example1.cs(10) : warning BC42104: Variable //names// is used before it
    //    has been assigned a value. A null reference exception could result
    //    at runtime.
    //
    //          names.Add("Major Major Major")
    //          ~~~~~
    // The example displays output like the following output:
    //    Unhandled Exception: System.NullReferenceException: Object reference
    //    not set to an instance of an object.
    //       at Example.Main()
    

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

    C#
    using System;
    using System.Collections.Generic;
    
    public class Example
    {
       public static void Main()
       {
          List<String> names = new List<String>();
          names.Add("Major Major Major");
       }
    }
    
  • Вы забыли измерение массива перед его инициализацией. В следующем примере values объявляется целым массивом, но количество элементов, содержащихся в нем, никогда не указывается. Поэтому попытка инициализировать свои значения создает NullReferenceException исключение.

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
           int[] values = null;
           for (int ctr = 0; ctr <= 9; ctr++)
              values[ctr] = ctr * 2;
    
           foreach (var value in values)
              Console.WriteLine(value);
       }
    }
    // The example displays the following output:
    //    Unhandled Exception:
    //       System.NullReferenceException: Object reference not set to an instance of an object.
    //       at Example.Main()
    

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

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
           int[] values = new int[10];
           for (int ctr = 0; ctr <= 9; ctr++)
              values[ctr] = ctr * 2;
    
           foreach (var value in values)
              Console.WriteLine(value);
       }
    }
    // The example displays the following output:
    //    0
    //    2
    //    4
    //    6
    //    8
    //    10
    //    12
    //    14
    //    16
    //    18
    

    Дополнительные сведения об объявлении и инициализации массивов см. в разделе Массивы и массивы.

  • Вы получаете возвращаемое значение NULL из метода, а затем вызываете метод для возвращаемого типа. Иногда это является результатом ошибки документации; В документации не отмечается, что вызов метода может возвращать null. В других случаях код ошибочно предполагает, что метод всегда возвращает значение, отличное от NULL .

    Код в следующем примере предполагает, что Array.Find метод всегда возвращает Person объект, поле которого FirstName соответствует строке поиска. Так как совпадения нет, среда выполнения создает NullReferenceException исключение.

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Person[] persons = Person.AddRange( new String[] { "Abigail", "Abra",
                                              "Abraham", "Adrian", "Ariella",
                                              "Arnold", "Aston", "Astor" } );
          String nameToFind = "Robert";
          Person found = Array.Find(persons, p => p.FirstName == nameToFind);
          Console.WriteLine(found.FirstName);
       }
    }
    
    public class Person
    {
       public static Person[] AddRange(String[] firstNames)
       {
          Person[] p = new Person[firstNames.Length];
          for (int ctr = 0; ctr < firstNames.Length; ctr++)
             p[ctr] = new Person(firstNames[ctr]);
    
          return p;
       }
    
       public Person(String firstName)
       {
          this.FirstName = firstName;
       }
    
       public String FirstName;
    }
    // The example displays the following output:
    //       Unhandled Exception: System.NullReferenceException:
    //       Object reference not set to an instance of an object.
    //          at Example.Main()
    

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

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Person[] persons = Person.AddRange( new String[] { "Abigail", "Abra",
                                              "Abraham", "Adrian", "Ariella",
                                              "Arnold", "Aston", "Astor" } );
          String nameToFind = "Robert";
          Person found = Array.Find(persons, p => p.FirstName == nameToFind);
          if (found != null)
             Console.WriteLine(found.FirstName);
          else
             Console.WriteLine("{0} not found.", nameToFind);
       }
    }
    
    public class Person
    {
       public static Person[] AddRange(String[] firstNames)
       {
          Person[] p = new Person[firstNames.Length];
          for (int ctr = 0; ctr < firstNames.Length; ctr++)
             p[ctr] = new Person(firstNames[ctr]);
    
          return p;
       }
    
       public Person(String firstName)
       {
          this.FirstName = firstName;
       }
    
       public String FirstName;
    }
    // The example displays the following output:
    //        Robert not found
    
  • Вы используете выражение (например, объединяете в цепочку список методов или свойств) для получения значения, и, хотя вы проверяете, является nullли значение , среда выполнения по-прежнему NullReferenceException создает исключение. Это происходит потому, что одно из промежуточных значений в выражении возвращает null. В результате тест для null никогда не оценивается.

    В следующем примере определяется Pages объект , который кэширует сведения о веб-страницах, представленных объектами Page . Метод Example.Main проверяет, имеет ли текущая веб-страница заголовок, отличный от NULL, и, если он есть, отображает заголовок. Однако, несмотря на это проверка, метод создает NullReferenceException исключение.

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          var pages = new Pages();
          if (! String.IsNullOrEmpty(pages.CurrentPage.Title)) {
             String title = pages.CurrentPage.Title;
             Console.WriteLine("Current title: '{0}'", title);
          }
       }
    }
    
    public class Pages
    {
       Page[] page = new Page[10];
       int ctr = 0;
    
       public Page CurrentPage
       {
          get { return page[ctr]; }
          set {
             // Move all the page objects down to accommodate the new one.
             if (ctr > page.GetUpperBound(0)) {
                for (int ndx = 1; ndx <= page.GetUpperBound(0); ndx++)
                   page[ndx - 1] = page[ndx];
             }
             page[ctr] = value;
             if (ctr < page.GetUpperBound(0))
                ctr++;
          }
       }
    
       public Page PreviousPage
       {
          get {
             if (ctr == 0) {
                if (page[0] == null)
                   return null;
                else
                   return page[0];
             }
             else {
                ctr--;
                return page[ctr + 1];
             }
          }
       }
    }
    
    public class Page
    {
       public Uri URL;
       public String Title;
    }
    // The example displays the following output:
    //    Unhandled Exception:
    //       System.NullReferenceException: Object reference not set to an instance of an object.
    //       at Example.Main()
    

    Исключение возникает, так как pages.CurrentPage возвращает значение null , если в кэше нет сведений о странице. Это исключение можно исправить, проверив CurrentPage значение свойства перед получением свойства текущего Page объекта Title , как показано в следующем примере:

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          var pages = new Pages();
          Page current = pages.CurrentPage;
          if (current != null) {
             String title = current.Title;
             Console.WriteLine("Current title: '{0}'", title);
          }
          else {
             Console.WriteLine("There is no page information in the cache.");
          }
       }
    }
    // The example displays the following output:
    //       There is no page information in the cache.
    
  • Выполняется перечисление элементов массива, содержащего ссылочные типы, и попытка обработать один из элементов вызывает NullReferenceException исключение.

    В следующем примере определяется массив строк. Оператор for перечисляет элементы в массиве и вызывает метод каждой Trim строки перед отображением строки.

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          String[] values = { "one", null, "two" };
          for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
             Console.Write("{0}{1}", values[ctr].Trim(),
                           ctr == values.GetUpperBound(0) ? "" : ", ");
          Console.WriteLine();
       }
    }
    // The example displays the following output:
    //    Unhandled Exception:
    //       System.NullReferenceException: Object reference not set to an instance of an object.
    //       at Example.Main()
    

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

    C#
    using System;
    
    public class Example
    {
       public static void Main()
       {
          String[] values = { "one", null, "two" };
          for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
             Console.Write("{0}{1}",
                           values[ctr] != null ? values[ctr].Trim() : "",
                           ctr == values.GetUpperBound(0) ? "" : ", ");
          Console.WriteLine();
       }
    }
    // The example displays the following output:
    //       one, , two
    
  • Исключение NullReferenceException может быть вызвано методом, когда он обращается к члену одного из своих аргументов, но этот аргумент имеет значение null. Метод PopulateNames в следующем примере создает исключение в строке names.Add(arrName);.

    C#
    using System;
    using System.Collections.Generic;
    
    public class Example
    {
       public static void Main()
       {
          List<String> names = GetData();
          PopulateNames(names);
       }
    
       private static void PopulateNames(List<String> names)
       {
          String[] arrNames = { "Dakota", "Samuel", "Nikita",
                                "Koani", "Saya", "Yiska", "Yumaevsky" };
          foreach (var arrName in arrNames)
             names.Add(arrName);
       }
    
       private static List<String> GetData()
       {
          return null;
       }
    }
    // The example displays output like the following:
    //    Unhandled Exception: System.NullReferenceException: Object reference
    //    not set to an instance of an object.
    //       at Example.PopulateNames(List`1 names)
    //       at Example.Main()
    

    Чтобы устранить эту проблему, убедитесь, что аргумент, передаваемый в метод, не nullявляется , или обработайте созданное исключение в блоке try…catch…finally . Дополнительные сведения см. в разделе Исключения.

Следующие инструкции microsoft intermediate language (MSIL) вызываютNullReferenceException: callvirt, cpblk, cpobj, initblk, ldelem.<type>, ldelema, ldfld, , ldflda, ldind.<type>, ldlen, , stind.<type>throwstelem.<type>stfldи .unbox

NullReferenceException использует COR_E_NULLREFERENCE HRESULT, которая имеет значение 0x80004003.

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

Обработка NullReferenceException в коде выпуска

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

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

  • Приложение может пропускать объекты, которые имеют значение null. Например, если приложение получает и обрабатывает записи в базе данных, можно игнорировать некоторое число неверных записей, которые вызывают возникновение объектов со значением null. Возможно, все, что потребуется, — записать неверные данные в файл журнала или интерфейс пользователя приложения.

  • Можно попытаться исправить исключение. Например, вызов веб-службы, возвращающей ссылочный тип, может возвращать значение NULL в случае потери соединения или превышения времени ожидания соединения. Вы можете попытаться восстановить подключение и повторить вызов.

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

  • Требуется сообщить об исключении. Например, если ошибка была вызвана ошибкой пользователя приложения, можно создать сообщение, которое поможет ему предоставить правильные сведения. Кроме того, можно зарегистрировать сведения об ошибке, которые помогут устранить проблему. Некоторые платформы, например, ASP.NET, содержат высокогоуровневый обработчик исключений, который перехватывает все ошибки, чтобы приложения никогда аварийно не завершало работу; в этом случае только благодаря регистрации исключения вы сможете узнать о наличии ошибки.

Конструкторы

NullReferenceException()

Инициализирует новый экземпляр NullReferenceException класса , присваивая Message свойству нового экземпляра системное сообщение, описывающее ошибку, например "Было найдено значение null, где требуется экземпляр объекта". В этом сообщении учитывается текущий язык и региональные параметры системы.

NullReferenceException(SerializationInfo, StreamingContext)
Устаревшие..

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

NullReferenceException(String)

Инициализирует новый экземпляр класса NullReferenceException с указанным сообщением об ошибке.

NullReferenceException(String, Exception)

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

Свойства

Data

Возвращает коллекцию пар «ключ-значение», предоставляющую дополнительные сведения об исключении.

(Унаследовано от Exception)
HelpLink

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

(Унаследовано от Exception)
HResult

Возвращает или задает HRESULT — кодированное числовое значение, присвоенное определенному исключению.

(Унаследовано от Exception)
InnerException

Возвращает экземпляр класса Exception, который вызвал текущее исключение.

(Унаследовано от Exception)
Message

Возвращает сообщение, описывающее текущее исключение.

(Унаследовано от Exception)
Source

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

(Унаследовано от Exception)
StackTrace

Получает строковое представление непосредственных кадров в стеке вызова.

(Унаследовано от Exception)
TargetSite

Возвращает метод, создавший текущее исключение.

(Унаследовано от Exception)

Методы

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
GetBaseException()

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

(Унаследовано от Exception)
GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetObjectData(SerializationInfo, StreamingContext)
Устаревшие..

При переопределении в производном классе задает объект SerializationInfo со сведениями об исключении.

(Унаследовано от Exception)
GetType()

Возвращает тип среды выполнения текущего экземпляра.

(Унаследовано от Exception)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
ToString()

Создает и возвращает строковое представление текущего исключения.

(Унаследовано от Exception)

События

SerializeObjectState
Устаревшие..

Возникает, когда исключение сериализовано для создания объекта состояния исключения, содержащего сериализованные данные об исключении.

(Унаследовано от Exception)

Применяется к

Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

См. также раздел