Lambda范围澄清

时间:2012-05-14 17:05:04

标签: c# .net c#-4.0 lambda scope

为什么我的参数x表现得如此不规律?

  1. 示例1 - 当前上下文中不存在。
  2. 示例2 - 无法重用x,因为它是在“子”范围内定义的。
  3. 例3 - 很好。这是我感到困惑的部分。也许是一个不同的“孩子”范围?
  4. 示例1

    List<int> list = new List<int> { 1, 2, 3, 4, 5 };
    var result = list.Where(x => x < 3);
    Console.Write(result.ElementAt(x));
    

    创建此编译时错误:

      

    当前上下文中不存在名称“x”

    我期待。

    示例2

    List<int> list = new List<int> { 1, 2, 3, 4, 5 };
    var result = list.Where(x => x < 3);
    int x = 1;
    Console.Write(result.ElementAt(x));
    

    产生这个编译时错误:

      

    无法在此范围内声明名为“x”的局部变量,因为它   会给'x'赋予不同的含义,它已经在a中使用了   '孩子'范围表示别的东西

    我理解这个问题中回答的范围,Is there a reason for C#'s reuse of the variable in a foreach?。然而,这是我以前从未见过的。此外,它使这个问题What is the scope of a lambda variable in C#?的答案不完整或错误。

    示例3

    List<int> list = new List<int> { 1, 2, 3, 4, 5 };
    List<string> stringList = new List<string> { "A", "B" };
    var result = list.Where(x => x < 3);
    var result2 = stringList.Where(x => x != "A");
    
    Console.Write(result2);
    

    没有产生错误。

    <小时/> 通过接受的答案,Eric Lippert的这些博客文章帮助我了解了正在发生的事情。如果有人仍然感到困惑:

    declaration space

    simple names

3 个答案:

答案 0 :(得分:17)

Example 1中,x在lamdba表达式的局部范围内定义,对第三行不可见

Example 2中,现在您已在同一声明范围内声明了两个名为“x”的变量(可见性不同)

使用lambda或匿名方法,它“捕获”它运行的范围。如果你有一个与lambda定义相同范围的本地x,那么它“捕获”x以拉入lambda可以访问的内容 - 从而产生两个“x”定义。您在lambda中声明的内容不会被捕获到另一个方向,因此它在lambda外部不可见。

Example 3中,现在你没有使用本地的变量只是lambda之外的lambda,而不是在相同的声明范围内命名相同的东西。

答案 1 :(得分:5)

子范围(示例3)可以使用相同的变量,但父级和子级不能重新声明变量。

您可以获得相同的内容:

// Child scopes
for (int i = 1; i < 10; i++){ /* do something */ }
for (int i = 1; i < 10; i++){ /* do something else */ }

这会失败:

// Child and parent
for (int i = 1; i < 10; i++){ /* do something */ }
int i = 33;

答案 2 :(得分:3)

它似乎并不复杂。

如果为lamda表达式定义参数,则该参数仅在lamda表达式的范围内有效

(int x) =>
{
   //x is only valid inside this scope
}

如果你有一个第二个变量,其定义在与lamda表达式相同的范围内,你将得到一个错误,因为这个第二个变量在lamda表达式的范围内也是有效的。

void Foo()
{

 int y;

 //y is valid in the scope of foo

 (int x) =>
 {
    //x is only valid inside this scope
    //y is valid in the scope of foo and the lamda expression
 }
}

在第三个示例中,您有两个不同的lamda表达式,因此有两个不同的范围