LAMBDA分配局部变量 [英] Lambda assigning local variables

查看:137
本文介绍了LAMBDA分配局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下来源:

 静态无效的主要(字串[] args)
{
布尔测试;

行动波长=()=> {测试= TRUE; };
拉姆达();

如果(测试)
Console.WriteLine(OK);
}



应该编译,对不对?那么,事实并非如此。我的问题是:按C#标准,在该代码编译或这是一个编译器错误





中的错误消息:

 未分配的局部变量的使用'测试'

注意:我的知道的,如何修正这个错误,我的部分知道的,为什么它会发生。然而,局部变量被分配无条件,我想,那编译器的的通知说,但事实并非如此。我想知道,为什么






评论答案:C#的允许的声明未分配的变量,这就是其实非常有用,即

 布尔COND1,COND2; 
如果(someConditions)
{
COND1 = someOtherConditions1;
COND2 = someOtherConditions2;
}
,否则
{
COND1 = someOtherConditions3;
COND2 = someOtherConditions4;
}



编译器正确编译的代码,我认为,在离开变量未分配实际上使码好一点点,这是因为:




  • 它告诉读者,值(在下面的条件语句大多可能)分配后

  • 迫使程序员分配的内部条件的所有分支机构的变量(如果它是从一开始这个代码的目的),因为编译器会拒绝,如果其中一个分支的编译代码不分配其中之一。






在保证金
这更有趣。考虑C ++相同的例子:

  INT主(INT ARGC,CHAR *的argv [])
{
布尔测试;

/ *注释或取消注释该块
自动波长= [&放大器;(){测试= TRUE; };
拉姆达();
* /

如果(测试)
的printf(OK);

返回0;
}

如果你对此有何评论块出来,编译有警告结尾:



  main.cpp中(12):警告C4700:未初始化的局部变量测试使用

不过,如果你删除注释,编译器会发出没有任何警告。在我看来,它是能够确定,如果变量被设置后,所有的。


解决方案

我的问题是:按C#标准,在该代码编译或
这是一个编译器错误




这?是不是一个错误。



C#语言规范(4.0)列出了有关匿名函数,包括lambda表达式明确赋值规则。我将张贴在这里。




5.3.3.29匿名函数



有关的lambda表达式或匿名方法表达式expr与身体(阻止或
表达式)正文:





  • 前体的外部变量v的明确赋值状态是一样的诉位于expr之前的状态。也就是说,外部变量的确定
    赋值状态是从
    的匿名函数的上下文中继承。


  • 的明确赋值状态
    expr之后的外层变量v是相同的诉位于expr之前的状态。




的例子

 委托布尔滤波器(int i)以; 

无效F(){$​​ B $ B INT最大;

//错误,最多不明确赋值
过滤器f =(INT N)=> N'LT;最大;

最大= 5;
的DoWork(F);
}



生成一个编译时错误,因为最大未明确赋值
其中,匿名函数声明。这个例子

 委托无效D(); 

无效F(){$​​ B $ B INT N;
D D =()=> {N = 1; };

D();

//错误,n不明确赋值
Console.WriteLine(N);
}



也产生自分配到n在$ B编译时错误$ b匿名功能上的匿名函数外部N
的明确赋值状态没有影响。




您可以看到这适用于您的具体例子。变量测试没有特别lambda表达式的声明之前分配。它不是具体的lambda表达式的执行之前进行分配。它没有具体的lambda表达式执行完成之后分配。按规则,编译器不考虑变量在它的点明确赋值被读取如果语句。



至于为什么,我只能重复我对此事看,只有我能记得我不能产生联系,但C#不会尝试这样做,因为,虽然这是一个很小的情况下眼睛能看到,这是更为频繁,这种类型的分析将是不平凡的,实际上可能达到解决停机问题的情况。因此,C#保持简单,并要求您更容易应用和解决的规则行事。


Consider the following source:

static void Main(string[] args)
{
    bool test;

    Action lambda = () => { test = true; };
    lambda();

    if (test)
        Console.WriteLine("Ok.");
}

It should compile, right? Well, it doesn't. My question is: according to C# standard, should this code compile or is this a compiler bug?


The error message:

Use of unassigned local variable 'test'

Note: I know, how to fix the error and i partially know, why does it happen. However, the local variable is assigned unconditionally and I guess, that compiler should notice that, but it does not. I wonder, why.


Comment for answers: C# allows declaring unassigned variables and that's actually quite useful, ie.

bool cond1, cond2;
if (someConditions)
{
    cond1 = someOtherConditions1;
    cond2 = someOtherConditions2;
}
else
{
    cond1 = someOtherConditions3;
    cond2 = someOtherConditions4;
}

Compiler compiles this code properly and I think, that leaving variables unassigned actually makes the code a little bit better, because:

  • It tells the reader, that values are assigned later (mostly probably in the following conditional statement)
  • Forces the programmer to assign the variables in all branches of internal conditions (if it was the purpose of this code from the beginning), because compiler will refuse to compile the code if one of the branches does not assign one of them.

On the margin: That's even more interesting. Consider the same example in 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;
}

If you comment the block out, compilation ends with warning:

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

However, if you remove the comment, compiler emits no warnings whatsoever. It seems to me, that it is able to determine, if the variable is set after all.

解决方案

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

This is not a bug.

Section 5.3.3.29 of the C# Language Specification (4.0) outlines the definite assignment rules regarding anonymous functions, including lambda expressions. I will post it here.

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.

You can see how this applies to your specific example. The variable test is not specifically assigned prior to the declaration of the lambda expression. It is not specifically assigned prior to the execution of the lambda expression. And it is not specifically assigned after the completion of the lambda expression execution. By rule, the compiler does not consider the variable to be definitely assigned at the point of it being read in the if statement.

As for why, I can only repeat what I have read on the matter, and only what I can remember as I cannot produce a link, but C# does not attempt to do this because, although this is a trivial case that the eye can see, it is far more often the case that this type of analysis would be non-trivial and indeed could amount to solving the halting problem. C# therefore "keeps it simple" and requires you to play by much more readily applicable and solvable rules.

这篇关于LAMBDA分配局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆