相关疑难解决方法(0)

C#在foreach中重用变量是否有原因?

在C#中使用lambda表达式或匿名方法时,我们必须警惕对修改后的闭包陷阱的访问.例如:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); // access to modified closure
   ...
}
Run Code Online (Sandbox Code Playgroud)

由于修改后的闭包,上面的代码将导致Where查询中的所有子句都基于最终值s.

正如这里所解释的那样,这是因为上面循环中s声明的变量foreach在编译器中被翻译成这样:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

而不是像这样:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

正如这里所指出的,循环外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是你计划在循环范围之外使用变量:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
var finalString = s;
Run Code Online (Sandbox Code Playgroud)

但是,foreach循环中定义的变量不能在循环外使用: …

c# foreach lambda scope anonymous-methods

1631
推荐指数
4
解决办法
10万
查看次数

C#中lambda变量的范围是什么?

我对lambda变量的范围感到困惑,例如以下内容

var query = 
    from customer in clist
    from order in olist
    .Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==  // line 1
        olist.Where(o1 => o1.CustomerID == customer.CustomerID)        // line 2
             .Max(o1 => o1.OrderDate)                                  // line 3
    )
    select new {
        customer.CustomerID,
        customer.Name,
        customer.Address,
        order.Product,
        order.OrderDate
    };
Run Code Online (Sandbox Code Playgroud)

在第1行中,我声明了一个lambda变量'o',这意味着我不能在第2行再次声明它(或者至少编译器在我尝试时会抱怨)但是即使'o1'已经存在,它也不会抱怨第3行??

lambda变量的范围是什么?

c# lambda scope

65
推荐指数
3
解决办法
2992
查看次数

为什么我可以声明一个与父作用域中的变量同名的子变量?

我最近写了一些代码,我无意中将一个变量名重用作为一个动作的参数,该动作在一个已经具有同名变量的函数中声明。例如:

var x = 1;
Action<int> myAction = (x) => { Console.WriteLine(x); };
Run Code Online (Sandbox Code Playgroud)

当我发现重复时,我惊讶地发现代码编译并完美运行,根据我对 C# 中作用域的了解,这不是我所期望的行为。一些快速的谷歌搜索出现了抱怨类似代码确实会产生错误的SO 问题,例如Lambda Scope Clarification。(我将该示例代码粘贴到我的 IDE 中以查看它是否可以运行,只是为了确保它可以完美运行。)此外,当我在 Visual Studio 中进入“重命名”对话框时,第一个x被突出显示为名称冲突。

为什么这段代码有效?我在 Visual Studio 2019 中使用 C# 8。

c# lambda scope variable-names c#-8.0

26
推荐指数
1
解决办法
1231
查看次数

linq匿名方法中的局部变量范围(闭包)

Linq Query中声明的局部变量的范围是什么.

我正在编写以下代码

   static void Evaluate()
    {
        var listNumbers = Enumerable.Range(1, 10).Select(i => i);
        int i = 10;
    }
Run Code Online (Sandbox Code Playgroud)

编译器标记的错误在行int i = 10,说明

A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else 
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么会出现这个错误.

我的理解是,i在第一行之后(在foreach循环中)将超出范围.所以i可以再次宣布.

实际行为是i在第一行(在foreach循环中)之后无法访问,这是正确的.但i不能再宣布.这看起来很奇怪.

编辑这是基于安德拉斯的回应的以下问题.答案非常好,但会引起进一步的质疑.

  static void Evaluate3()
    {
        var listNumbers = Enumerable.Range(1, 10).Select(i => i);
        var listNumbers1 …
Run Code Online (Sandbox Code Playgroud)

.net c# linq closures anonymous-methods

6
推荐指数
1
解决办法
1256
查看次数