是否传递匿名/lambda函数以使没有参数的委托无效?[C#]
本文关键字:参数 无效 lambda 函数 是否 | 更新日期: 2023-09-27 18:24:16
我一直在探索C#委托和匿名/lambda函数,我对它们如何交互有一些问题。据我所知,一个简单的委托对象可以具有预定义的返回和参数类型,并且任何具有相同返回/参数类型的命名函数都可以分配给该委托。
然而,在我的情况下,我一直在开发一款游戏,玩家可以将多个命令排入他们的命令列表。在添加到命令列表后的某个时刻,命令最终由玩家执行。。
我开始通过为每个命令(AttackCommand、HealCommand等)创建特定的子类来实现这一点,但后来发现,在构建各种新命令的原型时,这是非常乏味的。出于测试目的,我认为创建一个带有成员委托的CustomCommand类会很酷,这样我就可以匿名定义和传递函数,并快速迭代新的游戏设计思想。
public class CustomCommand : Command {
public delegate void CommandDelegate();
private CommandDelegate func;
public CustomCommand( CommandDelegate del ){
func = del;
}
public Execute(){
func();
}
}
然后Player有一个方法来定义一个匿名函数,并使用它来构造CustomCommand。然而,让我有点困惑的是,这个方法的参数似乎可以存储在CustomCommand的委托中:
//inside Player class..
//command to steal gold from a target!
public CreateCustomCommand( Player targetPlayer ){
CustomCommand.CommandDelegate anonCommand = delegate()
{
//Steals up to amount passed..
int goldToSteal = targetPlayer.StealGold(25);
gold += goldToSteal;
};
CustomCommand newCommand = new CustomCommand( anonCommand );
commandList.Enqueue( newCommand );
}
//Command is automatically executed later..
我试过这个代码,它不仅可以编译,而且还可以工作;资金从目标处被盗,并添加到源玩家中。我很高兴它能起作用,但有点令人不安的是,我不确定幕后到底发生了什么。。
以下是我很难理解的内容:
在(Player的)CreateCustomCommand方法中,gold在作用域中,因为它是Player类的成员,targetPlayer在作用域内,因为它为参数。。但是,如何将这些东西封装在一个匿名函数中,并传递给另一个对象中的一个空的、无参数的委托,并且仍然有效呢?这里发生了什么?匿名函数的创建是否存储对其包含的所有对象的引用?
与将命名函数分配给具有匹配返回/参数类型的委托相比,这似乎非常灵活,但是否存在任何主要缺点或陷阱?此外,这种技术是否与任何特定的设计模式或编程方法有关(或是其中的一部分)?
如果我正确理解这一点,这是有效的,因为匿名函数使用闭包。闭包是可以捕获(请参见:Lambda表达式中的变量作用域)生成闭包的可变环境的代码块。
因此,因为CreateCustomCommand方法定义了一个匿名函数(闭包),所以匿名函数捕获并维护了对CreateCustomCommand范围内变量的访问。
感谢@HansPassant为我指明了正确的方向!