Spo*_*ook 11 c# c++ lambda compiler-errors local-variables
请考虑以下来源:
static void Main(string[] args)
{
bool test;
Action lambda = () => { test = true; };
lambda();
if (test)
Console.WriteLine("Ok.");
}
Run Code Online (Sandbox Code Playgroud)
它应该编译,对吗?嗯,事实并非如此.我的问题是:根据C#标准,这个代码应该编译还是这个编译器错误?
Use of unassigned local variable 'test'
Run Code Online (Sandbox Code Playgroud)
注意:我知道,如何修复错误,我部分知道,为什么会发生.但是,无条件地分配了局部变量,我想,编译器应该注意到,但事实并非如此.我想知道为什么.
评论答案:C#允许声明未分配的变量,这实际上非常有用,即.
bool cond1, cond2;
if (someConditions)
{
cond1 = someOtherConditions1;
cond2 = someOtherConditions2;
}
else
{
cond1 = someOtherConditions3;
cond2 = someOtherConditions4;
}
Run Code Online (Sandbox Code Playgroud)
编译器正确编译了这段代码,我认为,保留未分配的变量实际上会使代码更好一些,因为:
在边缘:这更有趣.考虑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;
}
Run Code Online (Sandbox Code Playgroud)
如果您对块进行注释,则编译以警告结束:
main.cpp(12): warning C4700: uninitialized local variable 'test' used
Run Code Online (Sandbox Code Playgroud)
但是,如果删除注释,编译器不会发出任何警告.在我看来,它能够确定是否设置了变量.
Ant*_*ram 17
我的问题是:根据C#标准,这个代码应该编译还是这个编译器错误?
这不是一个错误.
C#语言规范(4.0)的第5.3.3.29节概述了有关匿名函数的明确赋值规则,包括lambda表达式.我会在这里发布.
5.3.3.29匿名函数
对于具有正文(块或表达式)主体的lambda表达式或匿名方法表达式expr:
在body之前的外部变量v的明确赋值状态与在expr之前的v的状态相同.也就是说,外部变量的明确赋值状态是从匿名函数的上下文继承的.
expr之后的外部变量v的明确赋值状态与expr之前的v的状态相同.
这个例子
Run Code Online (Sandbox Code Playgroud)delegate bool Filter(int i); void F() { int max; // Error, max is not definitely assigned Filter f = (int n) => n < max; max = 5; DoWork(f); }生成编译时错误,因为在声明匿名函数的地方没有明确赋值.这个例子
Run Code Online (Sandbox Code Playgroud)delegate void D(); void F() { int n; D d = () => { n = 1; }; d(); // Error, n is not definitely assigned Console.WriteLine(n); }因为在匿名函数中对n的赋值对匿名函数外的n的明确赋值状态没有影响,所以也会生成编译时错误.
您可以看到这适用于您的具体示例.test在声明lambda表达式之前未特别指定变量.在执行lambda表达式之前没有特别指定它.并且在lambda表达式执行完成后没有专门分配它.根据规则,编译器不会认为变量在if语句中被读取时被明确赋值.
至于为什么,我只能重复我在这个问题上所阅读的内容,而且只有我能记住的东西,因为我无法生成链接,但C#并不会尝试这样做,因为尽管这是一个微不足道的案例,眼睛可以看到更常见的情况是,这种类型的分析是非常重要的,实际上可能等于解决停止问题.因此,C#"保持简单",并要求您通过更容易应用和可解决的规则来玩.
您正在使用未分配的变量.即使实际分配了变量,编译器也无法从您发布的代码中推断出该变量.
无论如何都应该初始化所有局部变量,所以这很有趣,但仍然是错误的.