将值类型捕获到lambda中时是否执行复制?
struct SomeStruct { public int Num { get; set; } } class Program { static Action action; static void Foo() { SomeStruct someStruct = new SomeStruct { Num = 5 }; action = () => Console.WriteLine(someStruct.Num); } static void Main() { Foo(); action.Invoke(); } }
- 是否创建了lambda时创建的someStruct的副本?
- Foo返回时是否创建了someStruct的副本?
- 我可以validation没有发生复制吗? 在C ++中,我实现了复制构造函数并从中进行打印。
该标准的引文将不胜感激。 任何相关的在线文章也是如此。
没有副本。 Lambdas捕获变量,而不是值。
您可以使用Reflector查看编译代码:编译器会将“someStruct”变量移动到辅助类中。
private static void Foo() { DisplayClass locals = new DisplayClass(); locals.someStruct = new SomeStruct { Num = 5 }; action = new Action(locals.b__1); } private sealed class DisplayClass { // Fields public SomeStruct someStruct; // Methods public void b__1() { Console.WriteLine(this.someStruct.Num); } }
复制结构永远不会导致用户定义的代码运行,因此您无法真正检查它。 实际上,代码将在分配给“someStruct”变量时进行复制。 即使对于没有任何lambdas的局部变量,它也会这样做。
它不会被复制,它会创建一个闭包。 基本上它会将结构封装在一个对象中,而不是在堆栈上创建它。
如果你想确定你总是可以使用reflection器,但没有必要,这个行为在Raymond Chen博客上有解释。
请参阅C#中匿名方法的实现及其后果(第1部分) 。 你的代码实际上是这样的:
class SomeHiddenClass { SomeStruct someStruct; someHiddenMethod() { Console.WriteLine(someStruct.Num); } } SomeHiddenClass someHiddenVar = new SomeHiddenClass(); someHiddenVar.someStruct.Num = 5; action = someHiddenVar.someHiddenMethod;
<开始自我推销>我刚才在博客上写了这篇文章。 http://crazorsharp.blogspot.com/2009/06/how-do-closures-captured-variables-work.html end self promotion>
不,它不会复制,出于同样的原因(编译器创建一个幕后类来保存值),当您在lambda中捕获变量时,不会创建其他值类型的副本。
例如,如果你这样做:
int i = 7; Action a = () => Console.WriteLine("lambda i=" + i); i++; a(); //prints 8 Console.WriteLine("main i=" + i); //prints 8
lambda与声明范围共享’i’。 你的结构也会发生同样的事情。 您可以将此作为测试来certificate不会发生复制。