我很想知道Lambda(当用作委托时)是否会在每次调用时创建一个新实例,或者编译器是否会找到一种方法来仅实例化一次委托并传入该实例。
更具体地说,我想为XNA游戏创建一个API,我可以使用lambda传递自定义回调。因为这将在Update方法中调用(每秒调用很多次),如果它每次都新建一个实例以传递委托,那将是非常糟糕的。
InputManager.GamePads.ButtonPressed(Buttons.A, s => s.MoveToScreen<NextScreen>());
答案 0 :(得分:3)
是的,它可以在以下情况下缓存它们:
using System;
class Program {
static void Main(string[] args) {
var i1 = test(10);
var i2 = test(20);
System.Console.WriteLine(object.ReferenceEquals(i1, i2));
}
static Func<int, int> test(int x) {
Func<int, int> inc = y => y + 1;
Console.WriteLine(inc(x));
return inc;
}
}
它创建一个静态字段,如果它为null,则用新委托填充它,否则返回现有委托。
输出10,20,真。
答案 1 :(得分:3)
我对你的问题很感兴趣,因为我只是假设这种事情总会产生一个新的对象,因此在经常被调用的代码中要避免。
我做了类似的事情,所以我想我会用ildasm来了解幕后究竟发生了什么。在我的情况下,事实证明每次调用委托时都会创建一个新对象,我不会发布我的代码,因为它相当复杂,并且不容易理解脱离上下文。这与MichaelGG提供的答案相冲突,我怀疑是因为在他的例子中他使用了静态函数。我建议你自己尝试一下,然后再设计一切,然后发现你有问题。 ildasm是可行的方式(http://msdn.microsoft.com/en-us/library/f7dy01k1.aspx),注意任何“newobj”行,你不需要那些。
还值得使用CLR Profile来查明lambda函数是否正在分配内存(http://www.microsoft.com/downloads/details.aspx?familyid=A362781C-3870-43BE-8926-862B40AA0CD0&displaylang=en)。它说它适用于框架2.0,但它也适用于3.5,它是最新版本。