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

我有一些代码,

int count = 0; list.ForEach(i => i.SomeFunction(count++)); 

这似乎没有增加计数。 计数是否按此值传递? 如果我在lambda中使用{}有什么区别吗?

 int count = 0; list.ForEach(i => { i.SomeFunction(count++); }); 

更新1

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

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

(也就是说,在我看来它应该是递增count ,因为它应该捕获原始引用直到闭包。澄清 – 虽然计数将通过值传递到SomeFunction,但事情不会得到“当你在表达式中使用它们时,将它们传递给你的lambda表达式 – 它们与外部变量的引用相同。)

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

Bill Wagner有一本名为More Effective C#的好书,他有一篇博文,更详细地介绍了闭包 。

变量计数由您的情境中的lambda表达式捕获。 调用者可以看到对count任何更改。 所以,例如:

 int count = 0; list.ForEach(i => i.SomeFunction(count++)); Console.WriteLine(count); 

将显示列表的大小,因为在每次迭代时,您都会递增count

但是,对SomeFunction的调用会将count++的计算值(增量前的count 值)传递给SomeFunction 。 换句话说, SomeFunction不能改变count的值。

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

这应该增加,certificate:

 class Foo { public void SomeFunction(int i) { } } static void Main() { int count = 0; List list = new List {new Foo()}; list.ForEach(i => i.SomeFunction(count++)); Console.WriteLine(count); // 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 list = new List {new Foo()}; list.ForEach(scope.AnonMethod); Console.WriteLine(scope.count); // 1 } 

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

我想在这里添加一个小修正。 变量count既不是通过值传递,也不是通过引用lambda表达式传递,因为它不是参数。 相反,该值由闭包中的lambda 捕获

你应该查看Raymond的主题系列 – http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx

这应该捕获(关闭)计数作为一个闭包 。

不,没有区别。 参数通常是按值进行的,除非您在用于lambda的委托定义中明确地将其设为“ref”或“out”。

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

在这种情况下, 捕获 count变量。 即使它是一个struct ,捕获的变量就像它的引用一样 。 所以,你肯定会在foreach之后看到增加的count