Почему ссылочные типы не инициализируются нулем? - PullRequest
9 голосов
/ 06 января 2010

Проверьте этот код ..

    string str;

    if (str.Contains("something.."))
    {
    }

Компилятор выдает эту ошибку для этого кода

Использование неназначенной локальной переменной 'str'

Почему ссылочный тип не инициализируется нулем?

Просто хочу знать из любопытства.

Я также хотел бы знать, что происходит с кодом ниже. как работает это задание?

    string str = null;

Ответы [ 4 ]

22 голосов
/ 06 января 2010

Только поля (переменные, объявленные на уровне класса) инициализируются автоматически:

  • Типы значений инициализируются по умолчанию.
  • Типы ссылок инициализируются для null ссылок.

То, что вы объявляете, является "локальной переменной" внутри метода. Локальные переменные не инициализируются автоматически независимо от того, являются ли они типом значения или ссылочным типом.

Я также хотел бы знать, что происходит с кодом ниже. как работает это задание?

Это назначение инициализирует локальную переменную с нулевым значением с помощью инструкции ldnull, за которой следует инструкция stloc (конечно, если она не оптимизирована) и, что более важно, удовлетворяет правилам анализа потока данных компилятора для определенного назначения , Спецификация C # определяет концепцию, называемую определенным присваиванием, которая гарантирует присвоение переменной перед первым использованием.

7 голосов
/ 06 января 2010

Язык C # требует, чтобы все переменные были точно назначены до того, как они будут прочитаны. Локальные переменные считаются изначально неназначенными , тогда как поля, элементы массива и т. Д. Считаются , изначально присвоенными их значению по умолчанию . (Что для ссылочного типа равно нулю.)

Нет технической причины, по которой мы не могли бы обрабатывать локальные переменные как изначально присвоенные их значениям по умолчанию и отбрасывать всю проверку определенного присваивания. Это происходит потому, что использование неназначенного local в качестве значения по умолчанию является (1) плохой практикой кодирования и (2) весьма вероятным источником раздражающих ошибок. Требуя от вас явного назначения локальных переменных перед их использованием, мы предотвращаем использование недопустимой практики и устраняем целый класс ошибок, которые вам никогда не придется отлаживать.

Также учтите следующее:

while(whatever)
{
    int i;
    print(i);
    i = i + 1;
}

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

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

Я не знаю, как ответить на ваш второй вопрос, потому что я не знаю, что вы подразумеваете под «работой». Можете ли вы сказать мне, как присваивать "int x = 123;" работает? Как только я пойму, что вы подразумеваете под «работами», я могу описать, как работает присвоение нуля переменной ссылочного типа.

2 голосов
/ 06 января 2010

Это делает инициализированным нулевым значением. Компилятор только сделал вам одолжение, не отлаживая неизбежное исключение NullReferenceException, которое вы получите.

0 голосов
/ 06 января 2010

Помните также, что вызов Contains для пустой строки вызовет исключение NullReferenceException.

...