订阅作为参数传递的操作 [duplicate]

Subscribing to an action passed as an argument [duplicate]

提问人:Tagor 提问时间:6/22/2021 更新时间:6/22/2021 访问量:131

问:

我正在用 C# 为游戏制作有限状态机 (FSM)。目标是使其尽可能独立于传统控制流。我目前正在尝试用它创建枪支行为。 当枪进入“弹药不足”状态时,它应该开始侦听何时添加弹药并自动将状态更改为重新加载,但我在使用 C# 语言时遇到了一些问题。

我基本上想将一个 Action 传递给另一个函数。在该函数中,我想订阅它:

  var outOfAmmo = new ListenerState<GunState>(GunState.OUT_OF_AMMO);
  outOfAmmo.AddTrigger(currentAmmo.OnAdded, GunState.RELOAD);

功能:

public class ListenerState<TStateID> : State<TStateID>

    ...

    public void AddTrigger(Action trigger, TStateID next)
    {
        Action setState = () => fsm.SetState(next);
        OnEnter += () => trigger += setState; //When we enter "Out of ammo" start listening for when ammo is added.
        OnExit += () => trigger -= setState; //When we exit "Out of ammo" we don't want to change state to reloading when ammo is added anymore
    }

当调用 OnEnter 和稍后的触发器时,我希望调用 setState,但事实并非如此。

拉出 AddTrigger 的内容可使一切按预期工作:

  outOfAmmo.AddTrigger(currentAmmo.OnAdded, GunState.RELOAD);
  Action setReload = () => fsm.SetState(GunState.RELOAD);
  outOfAmmo.OnEnter += () => currentAmmo.OnAdded += setReload;
  outOfAmmo.OnExit += () => currentAmmo.OnAdded -= setReload;

我在这里举了一个较小的例子来说明这个问题:https://dotnetfiddle.net/MG1tve

我不确定这是怎么回事。

默认情况下,操作是否按值 :O 传递?因为作为 ref 传递可以解决问题 (https://dotnetfiddle.net/XNresg)

C# Unity-Game-Engine 按引用传递 -按值传递 FSM

评论

0赞 Peter Duniho 6/22/2021
委托是不可变的。您的参数变量由 lambda 处理程序修改,但除了使用变量本身的情况外,这不起作用,并且除了修改其值的处理程序之外,它不会用于其他任何用途。查看重复项。假设是一个字段而不是一个属性,你可以通过引用来传递它(即 with );这并不理想 - 可能有更好的方法来实现你正在尝试做的事情 - 但它会起作用。triggertriggerOnAddedref
0赞 Tagor 6/22/2021
谢谢,是的,OnAdded 是一个字段。但是,由于我在匿名方法中使用触发器,因此我真的可以使用ref吗?@PeterDuniho
0赞 Peter Duniho 6/22/2021
不,你是对的......不能在匿名方法中捕获 by-reference 参数。我想“这并不理想”是轻描淡写的。:)
0赞 Tagor 6/22/2021
@PeterDuniho是的,我完全重新设计了一切

答: 暂无答案