C# 是否将值传递给 Lambda?
我有一些代码,
int count = 0;
list.ForEach(i => i.SomeFunction(count++));
这似乎不会增加计数。 这里count是按值传递的吗? 如果我在 lambda 中使用 {} 有什么区别吗?
int count = 0;
list.ForEach(i =>
{
i.SomeFunction(count++);
});
更新 1
抱歉,我的错误,它确实更新了原始计数。
I have some code,
int count = 0;
list.ForEach(i => i.SomeFunction(count++));
This seems to not increment count. Is count passed by value here? Is there any difference if I use the {} in the lambda?
int count = 0;
list.ForEach(i =>
{
i.SomeFunction(count++);
});
Update 1
Sorry, my mistake, it does update the original count.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
count
是一个 int,而 int 是值类型,这意味着它们确实是按值传递的。 您的第一个示例和第二个示例之间没有语义差异。(也就是说,在我看来它应该递增
count
,因为它应该捕获原始引用直至闭包。澄清一下 - 尽管 count 将按值传递到 SomeFunction ,当您在表达式中使用它们时,事物不会“传递”到您的 lambda 表达式中——它们与外部变量是相同的引用。)count
is an int, and ints are value types, which means they are indeed passed by value. There is no semantic difference between your first and second example.(That said, it looks to me like it should be incrementing
count
, since it should be capturing the original reference as far as the closure. To clarify -- although count will be passed by value down into SomeFunction, things don't get "passed" into your lambda expression when you use them inside the expression -- they are the same reference as the external variable.)在这两种情况下,您都在创建所谓的闭包。 本质上,count 被包装在一个类中,并且该类由 lambda 表达式使用。
Bill Wagner 有一本很棒的书,名为更有效的 C#,他有一篇博客文章更详细地描述了闭包 。
In both cases you are creating what's called a closure. Essentially, count is being wrapped in a class and that class is being used by the lambda expression.
Bill Wagner has a great book called More Effective C# and he has a blog post that describes closures in more detail.
在您的情况下,变量计数由 lambda 表达式捕获。 对
count
的任何更改都将对调用者可见。 因此,例如:将显示列表的大小,因为在每次迭代中您都会增加
count
。但是,对
SomeFunction
的调用会按 value< 传递count++
的计算值(即递增之前count
的值) /em> 到SomeFunction
。 换句话说,SomeFunction
无法更改count
的值。有关闭包和变量捕获的更多信息,请参阅我的闭包文章。
The variable count is captured by the lambda expression in your situation. Any changes to
count
will be visible to the caller. So, for instance:will display the size of the list, because on each iteration you're incrementing
count
.However, the call to
SomeFunction
passes the evaluated value ofcount++
(which is the value ofcount
before the increment) by value toSomeFunction
. In other words,SomeFunction
can't change the value ofcount
.For more on closures and variable capture, see my closures article.
这应该增加,证明:
lambda 的作用(如前所述)“捕获”计数,本质上使代码如下:
上面是编译器如何解释委托 lambda 的粗略近似。 正如您所看到的,
count
是类中的一个字段,并且会递增。That should increment, proof:
The lambda acts (as already stated) to "capture" count, essentially making the code like:
The above is a rough approximation of how the compiler interprets a delegate lambda. As you can see, the
count
is a field on a class, and is incremented.我想在这里添加一个小修正。 变量 count 既不是通过值传递,也不是通过对 lambda 表达式的引用传递,因为它不是参数。 相反,该值由闭包中的 lambda捕获。
你应该看看雷蒙德关于这个主题的系列
- http://blogs.msdn.com/oldnewthing/archive /2006/08/02/686456.aspx
I wanted to add a small correction here. The variable count is neither passed by value or by reference to the lambda expression because it is not a parameter. The value is instead captured by the lambda in a closure.
You should check out Raymond's series on the subject
- http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
这应该将计数捕获为闭包。
That should capture (close over) count as a closure.
不,没有区别。 参数通常按值传递,除非您在用于 lambda 的委托定义中明确将其设置为“ref”或“out”。
No, there is no difference. Arguments are usually by value, unless you explicitly make it "ref" or "out" in the delegate definition used for the lambda.
Lambda 是匿名函数,因此遵循与将参数传递给函数相同的规则。
Lambdas are anonymous functions, and as such, follow the same rules as passing arguments into a function.
在本例中,
count
变量被捕获。 即使它是一个struct
,捕获的变量的行为就像它的引用。 因此,您肯定会在foreach
之后看到递增的count
。In this case, the
count
variable is captured. Even if it's astruct
the captured variable acts like its a reference. So, you would certainly see an incrementedcount
after theforeach
.