Подтвердить что ты не робот

Исправление "Использование неназначенной локальной переменной" с нулевым присвоением. Зачем?

С куском кода, подобным этому, компилятор жалуется на c.MyProperty:

MyClass c;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // "Use of unassigned local variable 'c'".

Однако он не жалуется, если вы назначили null to c при инициализации:

MyClass c = null;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // no complains this time.

Итак, почему это работает? Если c не был присвоен null, и гипотетически допустил его компилятор, не было бы исключено одно и то же исключение в c.MyProperty, Ссылка на объект, не установленная на экземпляр объекта?

4b9b3361

Ответ 1

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

Вероятно, это связано с тем, что назначение null подразумевает явное действие разработчика.

Ответ 2

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

В соответствии со спецификацией null является литералом С#: "Нулевой литерал может быть неявно преобразован в ссылочный тип или тип с нулевым значением"

Как и в отношении присвоений: (взято из спецификации)

Начало цитаты, взятой из спецификации

5.3.3 Точные правила для определения определенного задания Чтобы определить, что каждая используемая переменная определенно назначена, компилятор должен использовать процесс, эквивалентный тому, который описан в этом разделе.

Компилятор обрабатывает тело каждого члена функции, у которого есть одна или несколько первоначально не назначенных переменных. Для каждой первоначально не назначенной переменной v компилятор определяет определенное состояние присваивания для v в каждой из следующих точек члена функции:

· В начале каждого утверждения

. В конечной точке (§8.1) каждого утверждения

. На каждой дуге, которая передает управление другому оператору или в конечную точку оператора

· В начале каждого выражения

. В конце каждого выражения

Конец цитаты

Таким образом, хотя значение null не указывает на объект в памяти, оно выполняет требования определенности, и поэтому компилятор допускает это.

Ответ 3

Это связано с тем, что спецификация языка С# v. 4.0 в разделе 1.6.6.2 "Тело метода и локальные переменные" гласит следующее:

Тело метода может объявлять переменные, которые являются специфическими для вызова метода. Такие переменные называются локальными переменными.

[пропущено]

С# требует, чтобы локальная переменная была определенно назначена, прежде чем ее значение может быть получено.

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

Ответ 4

Причиной этого исключения является то, что вы не присвоили значение по умолчанию для переменной, например

if (Request.Files != null  && Request.Files.Count > 0)
            {
                 Image = Request.Files.AllKeys[0];
            }
var stream  = new FileStream(Image,FileMode.Open);

теперь переменная Image выдаст ошибку компилятора

Использование неназначенной локальной переменной "Изображение"

Это связано с тем, что существует вероятность того, что условие станет истинным, и управление никогда не узнает, что такое переменная Image. поэтому либо поместите блок else, либо назначьте значение по умолчанию, как показано ниже.

string Image = "";
if (Request.Files != null  && Request.Files.Count > 0)
            {
                 Image = Request.Files.AllKeys[0];
            }
var stream  = new FileStream(Image,FileMode.Open);