c# - Lambda 分配局部变量

标签 c# c++ lambda compiler-errors local-variables

考虑以下来源:

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

如果您注释掉该 block ,编译将以警告结束:

main.cpp(12): warning C4700: uninitialized local variable 'test' used

但是,如果您删除注释,编译器将不会发出任何警告。在我看来,它能够确定是否最终设置了变量。

最佳答案

My question is: according to C# standard, should this code compile or is this a compiler bug?

这不是错误。

C# Language Specification 的第 5.3.3.29 节(4.0) 概述了关于匿名函数的明确赋值规则,包括 lambda 表达式。我会在这里发布。

5.3.3.29 Anonymous functions

For a lambda-expression or anonymous-method-expression expr with a body (either block or expression) body:

  • The definite assignment state of an outer variable v before body is the same as the state of v before expr. That is, definite assignment state of outer variables is inherited from the context of the anonymous function.

  • The definite assignment state of an outer variable v after expr is the same as the state of v before expr.

The example

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

generates a compile-time error since max is not definitely assigned where the anonymous function is declared. The example

delegate void D();

void F() {    
    int n;    
    D d = () => { n = 1; };

    d();

    // Error, n is not definitely assigned
    Console.WriteLine(n); 
}

also generates a compile-time error since the assignment to n in the anonymous function has no affect on the definite assignment state of n outside the anonymous function.

您可以看到这如何适用于您的具体示例。变量 test 没有在 lambda 表达式声明之前专门赋值。在执行 lambda 表达式之前,它不会被专门分配。并且在lambda表达式执行完成后并没有具体赋值。按照规则,编译器不会认为变量在 if 语句中被读取时已明确赋值。

至于为什么,我只能重复我读过的关于此事的内容,并且只能重复我记得的内容,因为我无法生成链接,但 C# 不会尝试这样做,因为尽管这是一个微不足道的案例,但眼睛可以看到,这种类型的分析往往是非常重要的,而且实际上可以解决停机问题。因此,C#“保持简单”并要求您按照更容易适用和可解决的规则进行游戏。

关于c# - Lambda 分配局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14224190/

相关文章:

c# - 确定 List<T> 中的值跳跃

c# - 如何在 WPF 应用程序中捆绑 View、ViewModel 和 DataTemplate 以便于重用?

c++ - 您可以指定线程终止的顺序,即线程依赖性吗?

c++ - DirectSoundBuffer8::锁定/解锁

c++ - Windows服务和客户端教程?

c# - 如何获取wpf按钮屏幕矩形

c# - 在 Silverlight 中将 windows-1252 编码转换为 UTF-8

c++ - 我如何将可调用对象传递给函数作为参数

具有只有一种方法的抽象类的 Java 8 lambda 表达式

c++ - undefined reference 捕获 lambda 中的静态变量