使用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();
}
}
}
}
}

我很抱歉,如果这不是对正在发生的事情的最好解释,或者代码转储不是解释我正在做的事情的最好方式。

不要将其作为方法传递,而是使用如下方式

CommandQueue.Command += doSomething;
void doSomething()
{
//doSomething
}

这样,当CommandQueue.Command函数在单独的类中运行时,它也会在主类中运行doSomething()void

委托不是方法调用,而是方法本身,接收者可以在需要的时候调用它,并带着它想要的参数。

下面是一个例子:

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);
}
}

这里有很多事情需要理解:

  1. c.DoSomething(this.MyMethod)行,this被捕获到您传递的委托中,这意味着当MyCallingClass.DoSomething调用该委托时,它将在MyClass的实例上被调用。c.DoSomething(MyClass.MyStaticMethod)行在没有实例的情况下调用它,因为它是一个静态方法。

  2. 这是MyCallingClass.DoSomething方法,它决定传递什么参数,而不是提供委托的方法。

  3. 如果你需要调用方提供参数,而调用方只决定何时调用,而不决定传递什么参数,那么你可以提前捕获参数,并传递一个不带参数的委托,如下所示。

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时求值,而不是在创建lambda时求值(惰性求值)。

  1. 您不必使用特定的delegate,而是可以使用Func<Vector3, int>,如下所示:
// Not actually needed.
// public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(Func<Vector3, int> method)
{
...
}
}

相关内容

  • 没有找到相关文章

最新更新