C # инициализация путаницы! - PullRequest
0 голосов
/ 07 мая 2009
int?  test;
try
{
    test = (int?) Int32.Parse ("7");
} catch {}

if (test == null)
     Console.WriteLine("test is null!");
else
     Console.WriteLine("test = {0}", test);

У меня есть некоторый код, который делает что-то ОЧЕНЬ похожее на это, та же идея на самом деле ... Создание переменной, попытка ее инициализации, затем проверка, чтобы убедиться, что инициализация прошла успешно.

Visual Studios выдает мне сообщение об ошибке «Использование неназначенной локальной переменной« test »», что несколько раздражает, это легко исправить, установив в первой строке:

int?  test = null;

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

Ответы [ 6 ]

5 голосов
/ 07 мая 2009

Проблема в блоке catch. Компилятор должен предположить, что код Int32.Parse может выдать и, следовательно, попасть в ваш блок catch. В этом случае строка Int32.Parse не завершается и, следовательно, тесту никогда не присваивается значение. Это означает, что строка «if» пытается использовать неинициализированное значение.

Вы можете исправить это с помощью

  1. Назначение тестового значения в блоке catch
  2. Инициализация его в null в начале метода
1 голос
/ 08 мая 2009

Вы можете избежать (int?) Приведения, чтобы сохранить 7 байтов для строки "= null":)

test = Int32.Parse ("7");
1 голос
/ 07 мая 2009

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

Эквивалентно (вместо присвоения test = null в объявлении) вы можете устранить ошибку, указав test = null в блоке catch, поскольку это будет означать, что независимо от пути, по которому идет код, назначается переменная test. Тем не менее, я думаю, что указанное вами разрешение (присвоение нулю в объявлении) является правильным - вы увидите это очень часто в C # -коде, который сильно разветвляется (с помощью операторов try-catch, if или любого другого) ) - и, честно говоря, это только помогает вам понять, для чего и когда вы присваиваете свои переменные, даже если это может показаться незначительным раздражением.

1 голос
/ 07 мая 2009

вы путаете разницу между объявлением переменной и инициализацией переменной

int?  test;

просто утверждает, что у вас есть переменная с именем test, которая имеет значение null int

но

int?  test = null;

утверждает, что у вас есть переменная с именем test, которая имеет значение null, и ее значение равно нулю

В VB нет различия, но в c # есть разница. Вот почему компилятор жалуется, потому что если что-то не получится в вашем блоке try, ваша тестовая переменная никогда не будет инициализирована.

0 голосов
/ 08 мая 2009

Я считаю, что этот стиль намного чище:

try
{
    int test = Int32.Parse("7");
    Console.WriteLine("Success!");
    // add return statement for successful execution here, if any
}
catch
{
    Console.WriteLine("Disaster!");
    // other return statement here, if any
}

Что касается ошибки компилятора: любое локальное поле должно быть явно инициализировано в пути кода перед его чтением. Это распространенная ошибка - не инициализировать локальные поля, поэтому это ошибка в C #. C / C ++ только предупреждает об этом, и он может дать * забавные * результаты, если он не инициализирован и значение отражает байты, которые уже были в стеке вызовов.

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

0 голосов
/ 07 мая 2009

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

...