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捕获 你应该看看雷蒙德关于这个主题的系列文章
-我建议不要在使用变量的同时修改变量,这样做不会节省大量的打字时间,也会带来无尽的麻烦。