Ошибка компилятора в зависимости от положения параметра в сигнатуре метода. Использование неназначенной локальной переменной
Допустим, у меня есть этот класс:
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
,