24

为什么我的参数x表现如此不稳定?

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

示例 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”赋予不同的含义,后者已在“子”范围中用于表示其他内容

我理解这个问题中回答的范围界定,C# 在 foreach 中重用变量是否有原因?. 然而,这是我以前从未见过的。此外,它还回答了这个问题,C# 中 lambda 变量的作用域是什么?,不完整或错误。

示例 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 的这些博客文章帮助我了解正在发生的事情。如果有人仍然感到困惑:

申报空间

简单的名字

4

3 回答 3

19

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

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

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

Example 3中,现在您没有使用仅在 lambda 之外的 lambda 本地变量,并且没有在同一声明范围内命名相同的东西。

于 2012-05-14T17:10:47.450 回答
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;
于 2012-05-14T17:16:56.307 回答
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
 }
}

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

于 2012-05-14T17:17:57.280 回答