假设我有这个类(class):

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);
}

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

这将导致编译错误:使用未分配的局部变量'boo'。首先,我了解为什么会发生这种情况,我可以通过添加以下内容进行修复:
Boo boo = null;

然后,在我的大声笑方法中,尽管首先执行 Foo ,但boo仍然为空。然后,如果我修改代码以使用 ref 像这样:
Lol(ref boo, Foo(out boo));
static void Lol(ref Boo boo, int n)
{
    Console.WriteLine(n);
    Console.WriteLine(boo);
}

我得到我是Boo!预期的。我不明白的原因是,如果我更改大声笑中的参数顺序并且不使用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);

这样就不会产生任何编译错误,而且除了我收到“我是Boo!”外,如预期的那样。

在调试时,我注意到在两种情况下(将int参数作为第一个参数,而将另一种方法作为参数)Foo首先执行。那么为什么编译器会显示此错误?

最佳答案

编译器从左到右评估参数表达式。所以在这一行:

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的堆栈中。

关于c# - 编译器错误取决于方法签名中的参数位置。使用未分配的局部变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42027669/

10-15 04:58