请考虑以下源代码:
static void Main(string[] args)
{
bool test;
Action lambda = () => { test = true; };
lambda();
if (test)
Console.WriteLine("Ok.");
}
它应该编译,对吗?但实际上并没有成功。我的问题是:根据C#标准,这段代码应该编译还是编译器出现了错误?
错误信息:
Use of unassigned local variable 'test'
注意:我知道如何修复错误,并且我部分地知道为什么会发生这种情况。然而,局部变量被无条件地赋值,我想编译器应该会注意到,但它没有。我想知道为什么。
回答评论:C#允许声明未赋值的变量,这实际上非常有用,即。
bool cond1, cond2;
if (someConditions)
{
cond1 = someOtherConditions1;
cond2 = someOtherConditions2;
}
else
{
cond1 = someOtherConditions3;
cond2 = someOtherConditions4;
}
编译器正确编译此代码,我认为,不给变量赋值实际上使代码更好,因为:
- 它告诉读者,值稍后被赋予(很可能在以下条件语句中)
- 强制程序员在内部条件的所有分支中分配变量(如果这是代码最初的目的),因为编译器将拒绝编译代码,如果其中一个分支没有分配其中一个变量。
在旁边说一下: 这更有趣。考虑C++中的同一示例:
int main(int argc, char * argv[])
{
bool test;
/* Comment or un-comment this block
auto lambda = [&]() { test = true; };
lambda();
*/
if (test)
printf("Ok.");
return 0;
}
如果您将该代码块注释掉,编译过程会以警告结束:
main.cpp(12): warning C4700: uninitialized local variable 'test' used
然而,如果您删除该注释,则编译器将完全没有任何警告。看起来对我来说,它能够确定变量最终是否被设置。
test
的行。我不知道这是否是因为基本的代码流分析没有跟随方法调用,还是因为当闭合局部变量转换为代码生成类成员时的方式,或者两者都有可能,也可能两者都不是。但无论如何,在声明时将变量初始化为 false。 - Anthony Pegramdelegate { test = true; };
)。其次,知道局部变量在委托中被赋值并不难。事实上,为了保持闭包语义,必须已经知道该局部变量在闭包中被访问并将其提升。困难的问题是确定是否在某个时候执行了该委托,并在那时将变量标记为具有定义的值。这是一个非平凡的一般情况问题。 - Servy