c# - 使用带参数的 C# 将方法作为参数传递 - 使用命令模式
问题描述
我是传递代表的新手,想知道以下代码是否可行?
CommandQueue.AddCommand(
new CommandItem(
group.MyGroupActionMovement(
new Vector3(-1000,-1000,-1000))));
好的,详细说明一下,我将对命令模式的错误尝试进行代码转储...
所以我正在尝试创建一个命令队列。仅从移动命令开始。它需要一个vector3作为参数。其他命令将具有不同的参数,例如枚举和游戏对象。
这应该是我的命令/操作界面,但是,我一直在弄乱它,看看我能做什么。
public class IGroupAction: MonoBehaviour
{
public delegate bool Del(Vector3 destination);
public virtual bool Execute()
{
return true;
}
}
这应该是命令/动作单元/项目
public class GroupActionItem
{
public IGroupAction MyGroupAction;
public GroupActionItem(IGroupAction.Del action)
{
}
public bool PerformAction()
{
return MyGroupAction.Execute();
}
}
这是我到目前为止完成的命令模式
public class GroupAction
{
public List<GroupActionItem> Actions;
public GroupAction()
{
Actions = new List<GroupActionItem>();
}
public void AddAction(GroupActionItem groupActionItem)
{
Actions.Add(groupActionItem);
}
public void ClearActions()
{
Actions.Clear();
}
public void PerformActions()
{
if (Actions.Count >= 1)
{
if(Actions[0].PerformAction())
{
Actions.Remove(Actions[0]);
}
}
}
}
这是我执行移动命令的地方
public class GroupActionMovement : IGroupAction
{
public override bool Execute()
{
return Movement();
}
public bool Movement(Vector3 destination)
{
return true;
}
}
public class Group : MonoBehaviour
{
public GroupActionMovement MyGroupActionMovement;
}
这是编码行为的执行。
public class Player : MonoBehaviour
{
public Dictionary<Group,GroupAction> PlayerGroupsActions;
public List<Group> Groups;
void Start()
{
PlayerGroupsActions = new Dictionary<Group, GroupAction>();
Groups = GetComponentsInChildren<Group>().ToList();
foreach (Group group in Groups)
{
GroupAction playerGroupActions = new GroupAction();
PlayerGroupsActions.Add(group,playerGroupActions);
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
//remove the foreach
foreach (Group group in Groups)
{
//directly apply the group
PlayerGroupsActions.TryGetValue(group, out GroupAction playerGroupActions);
if (playerGroupActions != null)
{
playerGroupActions.AddAction(new GroupActionItem(group.MyGroupActionMovement.Movement));
}
}
}
foreach (Group group in Groups)
{
PlayerGroupsActions.TryGetValue(group, out GroupAction playerFormationActions);
if (playerFormationActions != null)
{
if (playerFormationActions.Actions.Count != 0)
{
playerFormationActions.PerformActions();
}
}
}
}
}
如果这不是对正在发生的事情的最佳解释,或者代码转储不是解释我在做什么的最佳方式,我很抱歉。
解决方案
委托不是方法调用,而是它自己的方法,以便接收者在需要时使用它想要的参数调用它。
这是一个例子:
public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(new Vector3(-1000, -1000, -1000));
// Do something else.
}
}
public class MyClass
{
public static int MyStaticMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
int MyMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(this.MyMethod);
c.DoSomething(MyClass.MyStaticMethod);
}
}
这里有很多要理解的事情:
在第 行
c.DoSomething(this.MyMethod)
,this
被捕获到您传递的委托中,这意味着何时MyCallingClass.DoSomething
调用委托,它将在 的实例上调用MyClass
。该行将c.DoSomething(MyClass.MyStaticMethod)
在没有实例的情况下调用它,因为它是一个静态方法。这是
MyCallingClass.DoSomething
决定传递哪些参数的方法,而不是提供委托的方法。如果您需要调用者提供参数,而调用部分只决定何时调用而不决定传递哪些参数,那么您可以提前捕获参数,并传递不带参数的委托,如下所示。
public delegate int MyDelegate(); // No arguments anymore.
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(); // Not passing arguments anymore.
// Do something else.
}
}
public class MyClass
{
// ...
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(() => this.MyMethod(new Vector3(-1000, -1000, -1000)));
c.DoSomething(() => MyClass.MyStaticMethod(new Vector3(-1000, -1000, -1000));
}
}
如果您不熟悉语法() => ...
,这是一个 lambda 表达式,您可以将其视为动态创建的匿名函数。它仍然尊重原型返回一个int
并且不带参数。lambda 表达式现在捕获Vector3
实例的构造,因此将在调用 lambda 时使用此值。要理解的一个非常重要的方面是 lambda 表达式中的值是在调用 lambda 时计算的,而不是在创建时计算(惰性计算)。
- 您不必使用特定
delegate
的,而是可以使用 aFunc<Vector3, int>
,如下所示:
// Not actually needed.
// public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(Func<Vector3, int> method)
{
...
}
}
推荐阅读
- python - 使用 Python 从 .csv 中的 ESPNCricInfo StatsGuru 抓取数据
- javascript - jQuery 3.5.1 callback function in .animate() not working
- php - trim() 期望参数 1 是字符串
- html - 我的代码未在 index.html 文件中显示结果
- reactjs - 每次渲染组件时,react-map-gl 都会向其 api 发出请求
- c# - Trying To Get List To Only List Items With Matching ClientId
- firebase - 我想在颤动中从数组内部的地图中读取数据
- regex - 匹配具有随机开始和/或结束的字符串模式
- date - Dart:在字符串中找到第一个数字并剪切字符串
- rust - 宏可以简化特征 impl 吗?