Lambda assigning local variables

前端 未结 4 1810
太阳男子
太阳男子 2021-02-14 01:45

Consider the following source:

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

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

    if (test)
             


        
4条回答
  •  心在旅途
    2021-02-14 02:13

    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.

提交回复
热议问题