Почему " {"вызывает исключение NullReferenceException в статическом методе?
Это своего рода эзотерика. Я столкнулся с NullReferenceException при попытке открыть форму (в конструкторе winforms) в проекте winforms в visual studio 2008. Трассировка стека указывает на четвертую строку следующего кода:
public static class Logger
{
public static void LogMethodEnter()
{
var frame = new StackFrame(1);
var method = frame.GetMethod();
Trace.TraceInformation("{0}.{1}.{2}()", method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name);
Trace.Indent();
}
public static void LogMethodExit()
{
Trace.Unindent();
}
}
...имеется в виду линия с открывающейся фигурной скобкой. Я столкнулся с той же проблемой (но не с участием дизайнера winforms) в других проектах, и я думаю, что это была связанная с потоками проблема, но у меня нет кода для репликации он.
почему это происходит и почему трассировка стека исключений указывает на линию с фигурной скобкой?
пояснение: исключение нулевой ссылки происходит только в конструкторе winforms. Когда приложение запускается, оно не выдает эту ошибку.
5 ответов
Я предполагаю, что номера строк выключены (фактическая причина этого не так важна), и исключение фактически создается этим выражением:
method.DeclaringType.Namespace
и причина, по которой вы можете увидеть исключение NullReference, заключается в том, что new StackFrame(1)
выражение пара строк ранее иногда может возвращать пустой кадр. Пустой кадр означает вызов .GetMethod()
вернет null, и там вы идете.
почему вы иногда получаете пустой кадр, что компилятор just-in-time может выбрать встроенные короткие, неоднократно вызываемые методы, такие как в вашем коде. Это сбросит ваш стек вызовов, так что в лучшем случае вы получите метод более высокого уровня, чем вы намеревались, или в худшем случае (в вашем основном методе) нет более высокого метода, и вы получите null.
Я думаю, что у вас есть инициализация статического члена где-то в вашем классе, и что инициализатор бросает!--1-->. Кроме того, я думаю, у вас нет статического конструктора, поэтому ваш объект помечен как beforefieldinit и, следовательно,NullReferenceException
выбрасывается, когда ваш метод, который использует его, JITed.
что-то типа:
public static class Logger
{
private static object x = InitObjectX();
private static object InitObjectX() {
x.GetHashCode(); // Will throw since x is null.
}
public static void LogMethodEnter()
{
var frame = new StackFrame(1);
var method = frame.GetMethod();
Trace.TraceInformation("{0}.{1}.{2}()", method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name);
Trace.Indent();
}
public static void LogMethodExit()
{
Trace.Unindent();
}
}
возможно,.файл pdb содержит информацию о строке устарел.
чтобы исправить это, перестройте свой проект и убедитесь, что создание .pdb-файлы включены в настройках проекта. Для проектов C# это можно настроить на построить tab, установив Дополнительно -- > Отладочная Информация или полное или pdb-только.
Я думаю, что проблема связана со статическим методом, вызываемым до создания статического объекта. Я исправил проблему в проекте winforms, добавив статический конструктор.
Если я правильно помню, статический конструктор блокирует весь объект во время выполнения.
указание на фигурную скобку/, казалось бы, неправильная строка кода может когда-нибудь произойти. Я думаю, что это просто исключение произошло в предыдущей строке кода, и Visual Studio почему-то выделяет следующую строку.
на предположение, программа не может сломаться точно на линии, где произошло исключение из-за любого количества внутренних и внешних факторов.
Извините, я не могу объяснить это очень хорошо.