Ошибка ссылка на объект не указывает на экземпляр объекта арм фсс элн

При отладке кода, написанного на ряде языков программирования (Visual Studio, Pascal и других) программист может получить сообщение «Ссылка на объект не указывает на экземпляр объекта». Обычно это означает, что программа пытается обратиться к объекту, который не инициализирован (объекту не задано значение), и вместо значения объекта виден нуль (null). Давайте разберём суть и способы решения возникшей проблемы.

Окно ошибки ссылки на объект

   public class Product
{
    public string id { get; set; }
    public string name { get; set; }
    public string type { get; set; }
    public int price { get; set; }
    public int departmentId { get; set; }
    public int quantity { get; set; }
    public List<string> barcodes { get; set; }
    public string tax { get; set; }
}

Product product = new Product();
product.name = "Проверка";
product.type = "COUNTABLE";
product.departmentId = 114097;
product.quantity = 1000;
product.price = 333;
product.barcodes[0]= "2990000000002"; //ОШИБКА НА ЭТОЙ СТРОКЕ

product.tax = "NDS_NO_TAX";
  
  

задан 8 янв 2020 в 12:30

Андрей's user avatar

Вы обращаетесь к неинициализированной перемененной barcodes.

Можно инициализировать ее 3-мя способами:

1:

   public List<string> barcodes { get; set; } = new List<string>();
  
  
   public Product()
{
    barcodes = new List<string>();
}
  
  
   Product product = new Product();
product.barcodes = new List<string>();
  
  

ответ дан 8 янв 2020 в 12:37

OwDafuq's user avatar

5 серебряных знаков
19 бронзовых знаков

Проблема вот в чём. Программа нормально компилируется, а в Intellisense (то есть, в визуальном редакторе) возникает ошибка.

Редактор XAML пытается создать экземпляр TouristsListWnd
, чтобы нарисовать его. При этом он, понятно, пытается создать и экземпляр TouristsListViewModel
, потому что это часть XAML. Но в design-time конструктор, судя по всему, не срабатывает.

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

   if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
    return;
  
  

в начале конструктора.


Дополнение: заметьте, что объявление свойств с их инициализацией наподобие

   public MySqlConnection conn = new MySqlConnection(
            ConfigurationManager.ConnectionStrings["ConnectionString"].Conne‌​ctionString);
  
  

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

   public MySqlConnection conn;

public TouristsListViewModel()
{
    if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
        return;
    conn = new MySqlConnection(
            ConfigurationManager.ConnectionStrings["ConnectionString"].Conne‌​ctionString);
    ...
}
  
  

Заметьте, что нехорошо в конструкторе VM-объекта проводить длинную операцию — это затормозит UI-поток. Поэтому попробуем вынести чтение таблицы в отдельный поток. Получится что-то такое:

   public TouristsListViewModel()
{
    LoadData();
}

async void LoadData()
{
    InfoLabel.Text = "Loading database...";
    try
    {
        await Task.Run(() => LoadDataInBackground());
        InfoLabel.Text = null;
    }
    catch(MySqlException ex)
    {
        InfoLabel.Text = "Loading failed, error: " + ex.Message;
    }
}

void LoadDataInBackground()
{
    try {
        conn.Open();
        MySqlCommand cmd = new MySqlCommand("SELECT * FROM tourmanager.tourists;", conn);
        MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
        DataSet ds = new DataSet();
        adp.Fill(ds);

        foreach (DataRow dr in ds.Tables[0].Rows) {
            _tourists.Add(
                new Tourist((int)dr["id"], (string)dr["firstname"],
                            (string)dr["secondname"], (string)dr["patronymic"],
                            (string)dr["passport"], (string)dr["sex"]));
        }
    } finally {
        conn.Close();
    }
}
  
  
Содержание
  1. Что означает «Ссылка на объект не указывает на экземпляр объекта»?
  2. Более подробно
  3. Вкратце
  4. Примеры
  5. Цепочка
  6. Неявно
  7. Массив
  8. Элементы массива
  9. Массив массивов
  10. Collection/List/Dictionary
  11. LINQ
  12. События
  13. Неудачное именование переменных
  14. Цикл жизни страницы ASP. NET
  15. Сессии ASP. NET
  16. Пустые вью-модели ASP. NET MVC
  17. Как исправить дисфункцию, когда ссылка на необходимый объект не указывает на экземпляр объекта
  18. Простые примеры нулевых значений, вызывающих проблемы
  19. Отладка
  20. Способы избежать
  21. Явно проверять на null , пропускать код
  22. Явно проверять на null , использовать значение по умолчанию
  23. Явно проверять на null , выбрасывать своё исключение
  24. Использовать Debug.Assert для проверки на null для обнаружения ошибки до бросания исключения
  25. Использовать GetValueOrDefault() для Nullable типов
  26. Использовать оператор ?? (C#) или If() (VB)
  27. Использовать операторы ?. и ?[ (C# 6+, VB. NET 14+):
  28. Объединение нулей во избежание NullReferenceExceptions
  29. Использование условного оператора Null для избежания NullReferenceExceptions
  30. Заключение

Что означает «Ссылка на объект не указывает на экземпляр объекта»?

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

Читайте также:  Фонд социального страхования оренбург

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

Вы также можете столкнуться с исключением нулевой ссылки в ситуации, когда любой из типов объектов является нулём. Например, в приведенном ниже коде объект SqlCommand никогда не инициализируется. Отсутствие SQL-запроса может стать серьезной проблемой для вашего приложения. Иногда нулевую строку можно просто проигнорировать, и двигаться дальше. В других же случаях, как и в случае с SqlCommand, это может стать фатальной ошибкой, игнорировать которую не представляется возможным.

Объект SqlCommand


В данном отрывке объект SqlCommand никогда не инициализируется

Более подробно

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

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

   string foo = null;
foo.ToUpper();
  
  

Этот код выбросит исключение NullReferenceException
на второй строке, потому что вы не можете вызвать метод ToUpper()
у ссылки на string
, равной null
.

Вкратце

Вы пытаетесь воспользоваться чем-то, что равно null
(или Nothing
в VB. NET). Это означает, что либо вы присвоили это значение, либо вы ничего не присваивали.

Как и любое другое значение, null
может передаваться от объекта к объекту, от метода к методу. Если нечто равно null
в методе «А», вполне может быть, что метод «В» передал это значение в метод «А».

Остальная часть статьи описывает происходящее в деталях и перечисляет распространённые ошибки, которые могут привести к исключению NullReferenceException
.

Примеры

Несколько общих примеров, в которых возникает исключение.

Цепочка

   ref1.ref2.ref3.member
  
  

Если ref1
, ref2
или ref3
равно null
, вы получите NullReferenceException
. Для решения проблемы и определения, что именно равно null
, вы можете переписать выражение более простым способом:

   var r1 = ref1;
var r2 = r1.ref2;
var r3 = r2.ref3;
r3.member
  
  

Неявно

   public class Person {
    public int Age { get; set; }
}
public class Book {
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; // Свойство Author не было инициализировано
                                       // нет Person, у которого можно вычислить Age.
    }
}
  
  

То же верно для вложенных инициализаторов:

   Book b1 = new Book { Author = { Age = 45 } };
  
  

Несмотря на использование ключевого слова new
, создаётся только экземпляр класса Book
, но экземпляр Person
не создаётся, поэтому свойство Author
остаётся null
.

Массив

   int[] numbers = null;
int n = numbers[0]; // numbers = null. Нет массива, чтобы получить элемент по индексу
  
  

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

   Person[] people = new Person[5];
people[0].Age = 20; // people[0] = null. Массив создаётся, но не
                    // инициализируется. Нет Person, у которого можно задать Age.
  
  

Массив массивов

   long[][] array = new long[1][];
array[0][0] = 3; // = null, потому что инициализировано только первое измерение.
                 // Сначала выполните array[0] = new long[2].
  
  

Collection/List/Dictionary

   Dictionary<string, int> agesForNames = null;
int age = agesForNames["Bob"]; // agesForNames = null.
                               // Экземпляр словаря не создан.
  
  

LINQ

   public class Person {
    public string Name { get; set; }
}
var people = new List<Person>();
people.Add(null);
var names = from p in people select p.Name;
string firstName = names.First(); // Исключение бросается здесь, хотя создаётся
                                  // строкой выше. p = null, потому что
                                  // первый добавленный элемент = null.
  
  

События

   public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e); // Здесь бросится исключение, если на
                               // событие StateChanged никто не подписался
    }
}
  
  

Неудачное именование переменных

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

   public class Form1 {
    private Customer customer;

    private void Form1_Load(object sender, EventArgs e) {
        Customer customer = new Customer();
        customer.Name = "John";
    }

    private void Button_Click(object sender, EventArgs e) {
        MessageBox.Show(customer.Name);
    }
}
  
  

Можно избежать проблемы, если использовать префикс для полей:

   private Customer _customer;
  
  

Цикл жизни страницы ASP. NET

   public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // Выполняется только на первой загрузке, но не когда нажата кнопка
            myIssue = new TestIssue(); 
        }
    }
    
    protected void SaveButton_Click(object sender, EventArgs e)
    {
        myIssue.Entry = "NullReferenceException здесь!";
    }
}
  
  

Сессии ASP. NET

   // Если сессионная переменная "FirstName" ещё не была задана,
// то эта строка бросит NullReferenceException.
string firstName = Session["FirstName"].ToString();
  
  

Пустые вью-модели ASP. NET MVC

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

   // Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Модель не задана.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Исключение.
{
}
  
  

Читайте также:  ФСС Тимашёвск, официальный сайт, адрес и телефон на карте

Как исправить дисфункцию, когда ссылка на необходимый объект не указывает на экземпляр объекта

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

  • Инициализируйте переменные с допустимыми значениями;
  • Если переменная может быть нулевой, то проверьте код на нули, и обработайте его соответствующим образом;
  • Используйте оператор ? с методами, когда возможно. stringvar?ToUpper();
  • Применяйте инструменты уровня «Resharper» для выявления потенциальных нулевых ссылок.

Простые примеры нулевых значений, вызывающих проблемы

Наиболее распространёнными причинами рассматриваемой ошибки являются неверные настройки, вызовы базы данных, а также вызовы типа API, не возвращающие ожидаемые значения.

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

Отладка

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

Если вы хотите определить место, где значение ссылки устанавливается или не устанавливается, нажмите правой кнопкой на её имени и выберите «Find All References». Затем вы можете поставить точки останова на каждой найденной строке и запустить приложение в режиме отладки. Каждый раз, когда отладчик остановится на точке останова, вы можете удостовериться, что значение верное.

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

Способы избежать

Явно проверять на null
, пропускать код

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

   void PrintName(Person p) {
    if (p != null) {
        Console.WriteLine(p.Name);
    }
}
  
  

Явно проверять на null
, использовать значение по умолчанию

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

   string GetCategory(Book b) {
    if (b == null)
        return "Unknown";
    return b.Category;
}
  
  

Явно проверять на null
, выбрасывать своё исключение

Вы также можете бросать своё исключение, чтобы позже его поймать:

   string GetCategory(string bookTitle) {
    var book = library.FindBook(bookTitle);  // Может вернуть null
    if (book == null)
        throw new BookNotFoundException(bookTitle);  // Ваше исключение
    return book.Category;
}
  
  

Использовать Debug.Assert
для проверки на null
для обнаружения ошибки до бросания исключения

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

   string GetTitle(int knownBookID) {
    // Вы знаете, что метод не должен возвращать null
    var book = library.GetBook(knownBookID);  

    // Исключение будет выброшено сейчас, а не в конце метода.
    Debug.Assert(book != null, "Library didn't return a book for known book ID.");

    // Остальной код...

    return book.Title; // Не выбросит NullReferenceException в режиме отладки.
}
  
  

Однако эта проверка не будет работать в релизной сборке, и вы снова получите NullReferenceException
, если book == null
.

Использовать GetValueOrDefault()
для Nullable типов

   DateTime? appointment = null;
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Отобразит значение по умолчанию, потому что appointment = null.

appointment = new DateTime(2022, 10, 20);
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Отобразит дату, а не значение по умолчанию.
  
  

Использовать оператор ??
(C#) или If()
(VB)

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

   IService CreateService(ILogger log, Int32? frobPowerLevel)
{
    var serviceImpl = new MyService(log ?? NullLog.Instance);
    serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
}
  
  

Использовать операторы ?.
и ?[
(C# 6+, VB. NET 14+):

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

   var title = person.Title.ToUpper();
  
  

Если свойство Title
равно null
, то будет брошено исключение, потому что это попытка вызвать метод ToUpper
на значении, равном null
. В C# 5 и ниже можно добавить проверку:

   var title = person.Title == null ? null : person.Title.ToUpper();
  
  

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

   var title = person.Title?.ToUpper();
  
  

Разумеется, если переменная person
может быть равна null
, то надо проверять и её. Также можно использовать операторы ?.
и ??
вместе, чтобы предоставить значение по умолчанию:

   // обычная проверка на null
int titleLength = 0;
if (title != null)
    titleLength = title.Length;

// совмещаем операторы `?.` и `??`
int titleLength = title?.Length ?? 0;
  
  

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

   int firstCustomerOrderCount = customers?[0]?.Orders?.Count() ?? 0;
  
  

Объединение нулей во избежание NullReferenceExceptions

Еще одна замечательная особенность — объединение нулей (null coalescing), которое является оператором «??». Это прекрасно работает в случае получения значения по умолчанию для переменной, которая является нулём. Это работает со всеми типами данных, которые могут быть обнуляемыми. Следующий код генерирует исключение без объединения нулей. Добавление “?? new List<string>()» предотвращает исключение «Ссылка на объект не указывает на экземпляр объекта».

Читайте также:  Фонд социального страхования Инн и ФОНД СОЦИАЛЬНОГО СТРАХОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ

Пример исключения

Использование условного оператора Null для избежания NullReferenceExceptions

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

Пример кода

Заключение

В статье мы разобрали, что означает «Ссылка на объект не указывает на экземпляр объекта», в каких ситуациях она появляется, и как её исправить. Проверяйте объекты на наличие заданных значений, используйте «Resharper», и рассматриваемая нами ошибка перестанет вам досаждать.

Оцените статью
ФСС Help
Добавить комментарий