Ошибка компилятора в зависимости от положения параметра в сигнатуре метода. Использование неназначенной локальной переменной

Допустим, у меня есть этот класс:

class Boo
{
    public override string ToString()
    {
        return "I am Boo!";
    }
}

И эти методы:

static int Foo(out Boo boo)
{
    boo = new Boo();
    return 1;
}
static void Lol(Boo boo, int n)
{
    Console.WriteLine(n);
    Console.WriteLine(boo);
}

Сейчас в основном:

static void Main(string[] args)
{
    Boo boo;
    Lol(boo, Foo(out boo));
    Console.ReadLine();
}

Это приводит к ошибке компиляции: использование неназначенной локальной переменной 'boo'. Прежде всего, я понимаю, почему это происходит, я могу это исправить, добавив:

Boo boo = null;

Затем, в моем методе Lol, boo остается нулевым, несмотря на то, что Foo выполняется первым. Затем, если я изменю свой код для использования ref следующим образом:

Lol(ref boo, Foo(out boo));
static void Lol(ref Boo boo, int n)
{
    Console.WriteLine(n);
    Console.WriteLine(boo);
}

Я получил, я Бу! как и ожидалось. Я не понимаю, почему, если я изменяю порядок параметров в Lol и без использования ref и без инициализации boo, вот так:

static void Lol(int n, Boo boo) //order of the parameters has changed
{
    Console.WriteLine(n);
    Console.WriteLine(boo);
}

Lol(Foo(out boo), boo);

Тогда это не дает никакой ошибки компиляции и, кроме того, я получил "Я Бу!" как и ожидалось.

Во время отладки я заметил, что в обоих случаях (с параметром int в качестве первого и с другим способом) Foo выполняется первым. Тогда почему компилятор показывает эту ошибку?

1 ответ

Решение

Компилятор оценивает выражения аргумента слева направо. Итак, в этой строке:

Boo boo = null;
Lol(boo,Foo(out boo));

(без ref) boo оценивается первым (что приводит к null) и это значение результата (null) помещается в стек в качестве аргумента для Lol,

затем Foo(out boo) выполняется, который устанавливает значение вашего местного boo переменная, но не меняет значение уже в стеке для Lol,


С помощью ref ссылка на ваш местный boo переменная помещается в стек, так Lol будет читать значение как измененное Foo,


При изменении порядка параметров, Foo(out boo) оценивается / выполняется первым и boo инициализируется до того, как его значение помещается в стек для Lol,

Другие вопросы по тегам