Не инициализированная переменная в C#

У меня есть следующая часть кода:

class Foo
{

    public Foo()
    {
        Bar bar;
        if (null == bar)
        {

        }
    }
}

class Bar { }

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

Таким образом, теперь я задаюсь вопросом: каков vlaue панели, разве это не должно быть пустым? Разве они не установлены в NULL? (nullpointer?)

17
задан Zaid Masud 19 September 2012 в 17:44
поделиться

8 ответов

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

См. Раздел 5.3 спецификации C # 3.0 для получения дополнительных сведений об определенном назначении.

Обратите внимание, что это не имеет ничего общего с переменной ссылочного типа. Это не может быть скомпилировано таким же образом:

int i;
if (i == 0) // Nope, i isn't definitely assigned
{
}

1 Что касается языка, в любом случае ... очевидно, что место хранения в памяти имеет что-то , но это не имеет значения и зависит от реализации. Существует один способ узнать, что это за значение, создав метод с параметром out , но затем используя IL для просмотра значения этого параметра в методе, без придав ему другое значение. CLR совершенно не возражает против этого.Затем вы можете вызвать этот метод, передав переменную с неопределенным назначением, и вот, вы можете определить значение, которое, скорее всего, будет значением «все нули».

Я подозреваю, что спецификация CLI действительно предписывает локальным переменным иметь значение по умолчанию, но мне придется проверить. Если вы не делаете зла, подобного описанному выше, для вас это не имеет значения в C #.

36
ответ дан 30 November 2019 в 10:46
поделиться

Локальным переменным не присваивается значение по умолчанию. Вы должны инициализировать их, прежде чем использовать. Вы можете явно инициализировать null , хотя:

public Foo()
{
    Bar bar = null;
    if (null == bar)
    {

    }
}
2
ответ дан 30 November 2019 в 10:46
поделиться

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

(Локальная переменная, однако, может быть оптимизирована для использования регистра вместо пространства стека, но она все еще не определена.)

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

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

1
ответ дан 30 November 2019 в 10:46
поделиться

Это не имеет значения, потому что такой код не должен компилироваться каким-либо компилятором, реализующим C #.

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

0
ответ дан 30 November 2019 в 10:46
поделиться

Поля (переменные в классах / структурах) инициализируются значением null / zero / и т. Д. Локальные переменные ... ну - поскольку ("определенным назначением") вы не можете получить к ним доступ без назначения, нет разумного способа ответа; просто, это не определено, потому что это невозможно. Я считаю, что они оказываются нулевыми / нулевыми / и т. Д. (Можно доказать взломом некоторого из кода с помощью динамической генерации IL), но это деталь реализации.


Для информации, вот какой-то хитрый код, который показывает значение формально неинициализированной переменной:

using System;
using System.Reflection.Emit;
static class Program
{
    delegate void Evil<T>(out T value);
    static void Main()
    {
        MakeTheStackFilthy();
        Test();
    }
    static void Test()
    {
        int i;
        DynamicMethod mthd = new DynamicMethod("Evil", null, new Type[] { typeof(int).MakeByRefType()});
        mthd.GetILGenerator().Emit(OpCodes.Ret); // just return; no assignments
        Evil<int> evil = (Evil<int>)mthd.CreateDelegate(typeof(Evil<int>));
        evil(out i);
        Console.WriteLine(i);
    }
    static void MakeTheStackFilthy()
    {
        DateTime foo = new DateTime();
        Bar(ref foo);
        Console.WriteLine(foo);
    }
    static void Bar(ref DateTime foo)
    {
        foo = foo.AddDays(1);
    }
}

IL just выполняет "ret" - он никогда ничего не присваивает.

8
ответ дан 30 November 2019 в 10:46
поделиться

Нет, для локальных переменных автоматически не устанавливается значение 0 (по умолчанию).

Но поскольку вы (всегда) получаете эту ошибку, это не имеет значения. Если бы у него было другое значение, компилятор никогда не позволил бы вам узнать.

Не путать с полевыми переменными (членами класса), они инициализируются значением по умолчанию своего типа (0 / null / false / ...).

1
ответ дан 30 November 2019 в 10:46
поделиться

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

1
ответ дан 30 November 2019 в 10:46
поделиться

Помимо «корректности», инициализация локальной переменной также связана с процессом проверки среды CLR .
Для получения дополнительной информации см. Мой ответ на этот аналогичный вопрос: Почему локальные переменные должны иметь начальные значения

0
ответ дан 30 November 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: