假设我有这个课程:
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;
然后,在我的Lol方法中,尽管Foo首先执行,但是boo仍然为null 。然后,如果我修改代码以像这样使用ref:
Lol(ref boo, Foo(out boo));
static void Lol(ref Boo boo, int n)
{
Console.WriteLine(n);
Console.WriteLine(boo);
}
我知道我是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);
这样就不会产生任何编译错误,而且除了我收到“我是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
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句