Если значение int по умолчанию ноль, то почему C# не передаёт её в метод в качестве значения?

Если значение Типа int по умолчанию 0, то почему Компилятор не передаёт её в случае отсутствия значения переменной ?

int a;
int b = 5 + a;

Ответы (2 шт):

Автор решения: Andrey Tabakov

В мире программирования слишком много неопределённости. Компилятор подсказывает программисту, чтобы он явно указал то значение с которым хочет работать, а не предлагал компилятору неявно придумать его.

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

class Example {
    int field; // Поле класса - автоматически = 0.
    void Method() {
        int local; // Локальная переменная - не инициализирована.
        Console.WriteLine(field); // OK: 0.
        Console.WriteLine(local); // Ошибка
    }
}

В структуре нужно явно указать

struct MyStruct {
    public int Number;
    public MyStruct() { 
        Number = 0; // Если не проиницилизировать явно, будет ошибка
    }
}

В C# есть ключевое слово default (есть и выражение для классов default(T)), оно используется для явной инициализации значением по умолчанию.

int a = default;

Ну и напоследок значения массива также инициализируются дефолтными значениями

int[] arr = new int[5];
Console.WriteLine(arr[0]); // OK: 0

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

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

→ Ссылка
Автор решения: CrazyElf

Как сказано в спецификации языка C#:

A local variable introduced by a local_variable_declaration or declaration_expression is not automatically initialized and thus has no default value. Such a local variable is considered initially unassigned.

Я могу только предположить, почему так сделано. Переменные экземпляра класса всё-таки живут вместе с экземпляром класса, поэтому нет смысла что-то экономить на них. А вот локальные переменные могут использоваться только какой-то короткий момент общего времени жизни того контекста, в котором они определены. Поэтому компилятор может использовать различные оптимизации. Например, фактически выделять память под эту переменную не в том месте, где она описана, а только в том, где она реально используется. А может и вообще не выделять под неё память, если после оптимизации выяснится, что эта переменная может и вообще не нужна - например, она используется для каких-то промежуточных вычислений и тогда её значение можно просто использовать в процессе вычислений, не выделяя для неё какое-то отдельное место для хранения. Или, скажем, среда выполнения может выделять для переменной место на стеке или в регистре процессора.

Собственно, почему бы не инициализировать переменную всегда? Потому что копирование данных - это время, это такты процессора. Даже если это простейшие данные и мы просто кладём 0 в какую-то ячейку. Допустим, у нас есть какая-то функция, которая вызывается очень часто. И в ней есть переменная, которой что-то присваивается не сразу в начале, а после каких-то вычислений. Тогда начальное значение этой переменной просто не нужно. Можно выделить под неё память, не очищая её. Сэкономить таким образом несколько тактов процессора, которые, учитывая очень частые вызовы этой функции, дадут реальное ускорение работы.

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

→ Ссылка