Предупреждение о нулевой ссылке Visual Studio - почему нет ошибки?

StackOverflow https://stackoverflow.com/questions/1413210

Вопрос

Я заметил кое-что необычное в Visual Studio.Сначала попробуйте ввести это (C #) где-нибудь в функции:

class Foo  
{  
    public void Bar()  
    {  
        string s;
        int i = s.Length;
    }
}

Теперь, сразу же после этого, это будет означать s в s.Length в качестве ошибки, говоря "Use of unassigned local variable 's'".С другой стороны, попробуйте этот код:

class Foo  
{  
    private string s;
    public void Bar()  
    {  
        int i = s.Length;
    }
}

Он скомпилирует и подчеркнет s в private string s с предупреждением, гласящим: "Field 'Foo.s' is never assigned to, and will always have its default value null".

Теперь, если VS настолько умен и знает, что s всегда будет равно null, почему получение его длины во втором примере не является ошибкой?Мое первоначальное предположение было: "Это выдает ошибку компиляции только в том случае, если компилятор просто не может завершить свою работу.Поскольку технически код выполняется до тех пор, пока вы никогда не вызываете Bar() , это всего лишь предупреждение ". За исключением того, что объяснение недействительно в первом примере.Вы все еще можете запустить код без ошибок, если никогда не вызываете Bar().Так что же это дает?Просто оплошность, или я что-то упускаю?

Это было полезно?

Решение

Первый пример (ошибка) - это пример Отслеживание с определенным назначением , которое применяется только к локальным переменным. Из-за ограниченного контекста, компилятор имеет сжатый контроль над этой ситуацией. Обратите внимание, что s не является нулевым, оно не определено.

Во втором примере s является полем (по умолчанию равно нулю). Нет ошибки компилятора, но она всегда будет обнаружена во время выполнения. Этот конкретный случай может быть пойман в ловушку, но этот тип ошибки в общем случае не обнаруживается компилятором.
Например, вы можете добавить метод Bar2 () , который назначает строку для s , но вызывает ее позже, чем Bar () , или не все. Это устранило бы предупреждение, но не ошибку времени выполнения.

Так и есть по замыслу.

Другие советы

Для второго примера код допустим, он просто может выполняться некорректно.Вот несколько случаев, в которых эта программа могла бы "успешно" выполняться

  • Компилятор не корректен на 100%.Возможно, что "s" будет иметь ненулевое значение, если экземпляр будет изменен с помощью отражения.
  • Программа может выполняться без ошибок, если метод Bar никогда не вызывается
  • Эта программа может быть тестовой программой, которая запускает исключение NullReferenceException по причинам тестирования

Единственное, что я могу предположить, это то, что во втором примере s можно изменить с помощью отражения (используя BindingFlags.Private для доступа к закрытому члену).

В первом примере s является локальной переменной, и компилятор может легко проверить, что переменная s не была назначена перед ее использованием.

Во втором случае s является глобальной переменной, и, возможно, она была инициализирована где-то еще в классе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top