C#是否通过值传递给Lambdas?

C#是否通过值传递给Lambdas?,c#,.net,delegates,lambda,C#,.net,Delegates,Lambda,我有一些密码 int count = 0; list.ForEach(i => i.SomeFunction(count++)); 这似乎并不重要。这里的计数是按值传递的吗?如果我在lambda中使用{},有什么区别吗 int count = 0; list.ForEach(i => { i.SomeFunction(count++); }); 更新1 对不起,我弄错了,它确实更新了原始

我有一些密码

int count = 0;

list.ForEach(i => i.SomeFunction(count++));
这似乎并不重要。这里的计数是按值传递的吗?如果我在lambda中使用{},有什么区别吗

int count = 0;

list.ForEach(i => 
            {
                    i.SomeFunction(count++);
            });
更新1


对不起,我弄错了,它确实更新了原始计数。

不,没有区别。参数通常是按值传递的,除非在用于lambda的委托定义中显式将其设为“ref”或“out”。

count
是一个int,而int是值类型,这意味着它们确实是按值传递的。第一个示例和第二个示例之间没有语义差异


(这就是说,在我看来,它应该是递增的
count
,因为它应该捕获原始引用,直到闭包为止。澄清一下——虽然count将通过值向下传递到某个函数中,但不会“传递”当您在表达式中使用lambda表达式时,它们与外部变量的引用相同。)

应该捕获(关闭)计数为a。

lambda是匿名函数,因此,遵循与将参数传递到函数中相同的规则。

在这两种情况下,您都在创建所谓的闭包。本质上,count被包装在一个类中,并且lambda表达式正在使用该类


比尔·瓦格纳(Bill Wagner)有一本很棒的书,名为,他还写了一篇博文,详细描述了这本书。

这应该会增加,证明:

class Foo
{
    public void SomeFunction(int i) { }
}
static void Main()
{
    int count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(i => i.SomeFunction(count++));
    Console.WriteLine(count); // 1
}
class-Foo
{
公共函数(inti){}
}
静态void Main()
{
整数计数=0;
List List=新列表{new Foo()};
ForEach(i=>i.SomeFunction(count++);
Console.WriteLine(计数);//1
}
lambda(如前所述)用于“捕获”计数,基本上使代码类似于:

class Foo
{
    public void SomeFunction(int i) { }
}
class CaptureScope
{
    public int count;
    public void AnonMethod(Foo foo)
    {
        foo.SomeFunction(count++);
    }
}
static void Main()
{
    CaptureScope scope = new CaptureScope();
    scope.count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(scope.AnonMethod);
    Console.WriteLine(scope.count); // 1
}
class-Foo
{
公共函数(inti){}
}
类捕获镜
{
公共整数计数;
公共无效非方法(Foo-Foo)
{
SomeFunction(count++);
}
}
静态void Main()
{
CaptureScope scope=新CaptureScope();
scope.count=0;
List List=新列表{new Foo()};
list.ForEach(scope.AnonMethod);
Console.WriteLine(scope.count);//1
}

上面是编译器如何解释委托lambda的粗略近似。如您所见,
count
是类上的一个字段,并且是递增的。

在本例中,
count
变量是捕获的。即使它是一个
结构
,捕获的变量也像它的一个引用。因此,您肯定会看到在
foreach

之后,
count
会增加。在您的情况下,lambda表达式会捕获变量count。调用方将看到对计数的任何更改。例如:

int count = 0;
list.ForEach(i => i.SomeFunction(count++));
Console.WriteLine(count);
将显示列表的大小,因为在每次迭代中,您都在递增
count

但是,对
SomeFunction
的调用将
count++
的评估值(即增量之前的
count
值)按值传递给
SomeFunction
。换句话说,
SomeFunction
无法更改
count
的值


有关闭包和变量捕获的更多信息,请参阅我的。

我想在此添加一个小的更正。变量计数既不是通过值传递,也不是通过对lambda表达式的引用传递,因为它不是参数。值由闭包中的lambda捕获

你应该看看雷蒙德关于这个主题的系列文章
-

我建议不要在使用变量的同时修改变量,这样做不会节省大量的打字时间,也会带来无尽的麻烦。