"Ссылка на объект не набор к экземпляру объекта"
Почему исключение также не показывает название поля ссылки на объект или по крайней мере его тип?
Это - вероятно, одна из наиболее распространенных ошибок времени выполнения в.NET. Хотя Система. Исключение имеет отслеживание стека, нет никаких других полезных деталей.
В течение года я провожу часы, отсеивая через отслеживания стека (часто в коде, который я не написал), надеясь, что существует номер строки из ".pdb" файла, затем находя строку в коде, и даже затем это часто не очевидно, какая ссылка на строке была нулевой. Наличие названия поля ссылки было бы очень удобно.
Если Система. Экземпляры ArgumentNullException могут показать название параметра метода ("Значение, не может быть пустым. Название параметра: оцените"), затем конечно, Система. Экземпляры NullReferenceException могли включать название пустого поля (или его содержание набора).
Это было рассмотрено здесь: Определение целевого объекта при возникновении исключения NullReferenceException
и здесь: Почему исключение с нулевой ссылкой не может назвать объект с нулевой ссылкой?
Причина в основном в том, что среда выполнения не знает, когда встречается NRE. Я предполагаю, что ему придется работать со стеком вызовов и через дерево синтаксического анализа, что было бы очень дорого.
Даже если имя и тип переменной могут существовать в коде MSIL, они не будут существовать в родном коде, когда MSIL будет JITted.
Было бы невероятно неэффективно добавлять такую проверку в родной код во время JITting - по сути, это накладные расходы при каждом разыменовании указателя.
Разница между 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
, может оказаться сложной задачей.
Я не нашел это исключение таким уж трудным!
Если я знаю номер строки. Я просто вставляю точку останова на этой строке, запускаю приложение до этой строки, и когда отладчик останавливается, я навожу на каждую переменную/объект в этой строке, и благодаря Visual Studio, он показывает мне их значения.
Также я нашел окно Autos очень полезным в таких случаях, но процедура, которую я описал выше, быстро решает мою проблему.