"Ссылка на объект не установлена в экземпляр объекта": почему .NET не может показать более подробную информацию?
"Ссылка на объект не установлена в экземпляр объекта"
Почему исключение не показывает также имя поля ссылки объекта или, по крайней мере, его тип?
Это, вероятно, одна из самых распространенных ошибок времени выполнения в .NET. Хотя в System.Exception есть трассировка стека, нет других полезных сведений.
В течение года я часами просеиваю трассировку стека (часто в коде, который я не писал), надеясь, что есть номер строки из файла ".pdb", затем найдите строку в коде и даже то часто не очевидно, какая ссылка на строку была нулевой. Иметь имя ссылочного поля было бы очень удобно.
Если экземпляры System.ArgumentNullException могут показывать имя параметра метода ( "Значение не может быть пустым. Имя параметра: значение" ), то, безусловно, экземпляры System.NullReferenceException может включать имя нулевого поля (или содержащую его коллекцию).
Ответы
Ответ 1
Разница между ArgumentNullException
и NullReferenceException
заключается в том, что ArgumentNullException
всегда выбрасывается явно так:
if (parameter == null)
throw new ArgumentNullException("parameter");
Если бы быстрый просмотр вывода ILDASM, локальные переменные действительно присутствуют внутри функции IL. Однако API по-прежнему не существует для программного поиска этих имен. Я понимаю, что это было бы довольно сложно, поскольку вам в основном нужно было бы построить дерево синтаксического анализа, представляющее функцию с областями, переменными, утверждениями и т.д.
Это еще больше осложняется тем, что это не просто простые переменные, которые могут бросать NullReferenceException
, а результат вызова функции, свойства или выражения. Я мог бы довольно быстро успеть.
Представьте себе следующее:
internalObject.OtherProperty = myObject.GetOtherObject().ThirdObject.SomeProperty == "value"
? myObject.OtherProperty
: myObject.GetSomethingElse();
Там есть несколько точек отказа, и создание строки, представляющей фактически null
, может быть сложным.
Ответ 2
Здесь описано: Обнаружение целевого объекта при вызове NullReferenceException
и здесь: Почему не может исключить исключение с помощью NULL-объекта, у которого есть нулевая ссылка?
Причина в основном связана с тем, что среда выполнения не знает, когда встречается NRE. Я предполагаю, что ему придется работать со стоп-кадром и через дерево разбора, что было бы очень дорого.
Ответ 3
Несмотря на то, что имя и тип переменной могут существовать в коде MSIL, он не будет существовать в собственном коде, когда MSIL JITted.
Было бы невероятно неэффективно добавлять этот тип проверки в собственный код во время JITting - по существу, накладные расходы всякий раз, когда указатель разыменовывается.
Ответ 4
Я не нашел этого исключения, с которым трудно справиться!
Если я знаю номер строки. Я просто вставляю точку останова в эту строку, запускаю приложение в эту строку, и когда отладчик останавливается, я нахожу каждую переменную/объект в строке, и благодаря Visual Studio он показывает мне свои значения.
Также я нашел окно Autos очень полезным в таких случаях, но описанная выше процедура быстро решает мою проблему.