Почему неназначенные локальные переменные не инициализируются автоматически? - PullRequest
10 голосов
/ 17 октября 2011

Кажется, что нет никакого способа иметь неназначенные локальные переменные в вашем коде или проверять их, так как компилятор выдает ошибку Use of unassigned local variable.

Почему компилятор не использует default(T) для этих переменных во время компиляции?

Даже если это труднее сделать для типов значений, ссылочные типы можно легко инициализировать в null в этом случае, верно?

Вот тестовый код:

public void Test ( )
{
    int x;
    string s;

    if ( x == 5 )
        Console.WriteLine ( 5 );

    if ( s != null )
        Console.WriteLine ( "s" );
}

, который возвращает:

Use of unassigned local variable 'x'
Use of unassigned local variable 's'

UPDATE:

Для людей, которые утверждают, что это не разрешено по уважительной причине, почему это разрешено на уровне класса?

public class C
{
    public int X;
    public string S;

    public void Print ( )
    {
        Console.WriteLine ( X );
        Console.WriteLine ( S );
    }
}

Этот код прекрасно компилируется.

Почему нормально иметь на уровне класса, а не на уровне метода?

Ответы [ 6 ]

6 голосов
/ 17 октября 2011

Я вижу, вы обновили свой вопрос, поэтому я обновлю свой ответ.Ваш вопрос состоит из двух частей, одна из которых относится к local variables, а другая к instance variables on a class instance.Во-первых, однако, это на самом деле не решение о проектировании компилятора, а решение о проектировании языка.

Spec Раздел 12.3.1 / 12.3.2

Локальные переменные

Мы знаем , почему вы можете определить переменную, не задавая ей значение.Одна из причин, пример чего-то вроде этого:

int x;
// do stuff
x = 5;  // Wow, I can initialize it later!
Console.WriteLine(x);

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

Скажите, что код выше был вашим намерением, но вы забыли инициализировать x = 5;.Если бы компилятор автоматически инициализировал переменную для вас, код скомпилировался бы, но он не сделал бы ничего, как вы ожидаете.

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

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

Переменные экземпляра класса

Члены уровня класса определяются стандартом, который должен быть изначально назначен.На самом деле, чтобы быть справедливым, локальные переменные вне тех, которые объявлены в операторе catch, foreach или using, изначально не назначены.Так что на самом деле это проблема стандартов, а не проблема компилятора.

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

6 голосов
/ 17 октября 2011

C # - язык «ямы успеха».

Это дизайнерское решение, так как язык полностью позволяет вам использовать локальных пользователей, которые не были явно назначены. Однако обычно верно, что использование таких переменных является ошибочным, что путь кода по какой-то причине не установил значение. Чтобы избежать таких ошибок, компилятор требует, чтобы все локальные ресурсы были назначены перед использованием.

5 голосов
/ 17 октября 2011

1 Почему компилятор не позволяет использовать неинициализированные переменные?

Потому что предотвращение этого способствует хорошему программированию.

2 Почему компилятор допускает использование неинициализированных членов класса?

Потому что это невозможно отследить с какой-либо точностью.

1 голос
/ 17 октября 2011

Принимая ваше предложение об инициализации ссылочных типов в null вместо текущего поведения (глючный код вызывает ошибку времени компиляции), вы получите ошибку времени выполнения при разыменовании неинициализированной переменной.Вы действительно этого хотите?

0 голосов
/ 30 июня 2015

Рассмотрим следующий код:

void blah(IDictionary<int,int> dict)
{
  for (int i=0; i<10; i++)
  {
    if ((i & 11) != 0)
    {
        int j;
        dict.TryGetValue(i, out j);
        System.Diagnostics.Debug.Print("{0}",j);
        j++;
    }
  }
}

Предположим, что метод TryGetValue переданной реализации IDictionary<int,int> фактически никогда не записывает в j [невозможно, если он написан на C #,но возможно, если оно написано на другом языке].Что следует ожидать от кода, который будет напечатан?

Ничто в стандарте C # не требует сохранения j, когда код выходит из оператора if, но ничто не требует его сброса в ноль между итерациями цикла.Обязательное действие в некоторых случаях может привести к дополнительным расходам.Вместо того, чтобы делать что-либо, Стандарт просто позволяет, чтобы при вызове TryGetValue, j мог произвольно содержать ноль или последнее значение, которое он имел, когда находился в области видимости.Такой подход позволяет избежать ненужных затрат, но было бы неловко, если бы коду было позволено увидеть значение j между моментом повторного входа в область действия и временем ее записи (факт передачи неинициализированной переменной как outпараметр в коде, написанном на другом языке, будет показывать, что его значение было непреднамеренным).

0 голосов
/ 17 октября 2011

Потому что ты там хочешь? Вы хотите, чтобы x был нулем по умолчанию, и я хочу, чтобы он был 5 ...

если они присваивают 0 для int (s), и весь мир начинает предполагать это, то в какой-то момент они изменятся на -1, и это сломает так много приложений по всему земному шару.

в VB6 переменные были назначены чему-то по умолчанию, я думаю, и это было не так хорошо, как казалось.

когда вы используете C # или C ++, вы присваиваете значение с тем, что вам нужно, а не компилятором для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...