为了账号安全,请及时绑定邮箱和手机立即绑定

如何制作一个指向另一个动作 C# 的动作?

如何制作一个指向另一个动作 C# 的动作?

C#
森栏 2021-07-16 17:04:13
我在 C# 中遇到了一些意想不到的行为。我基本上是在尝试将一个操作分配给另一个操作的引用,以便我可以在以后订阅/取消订阅引用操作的方法。我不想知道实现引用操作的类。问题是,应该指向我想听的动作的动作似乎实际上并没有指向它。我认为每当提出引用的操作时它都会引发,但显然情况并非如此。我可能对代表有一些误解。有人可以告诉我我做错了什么吗?我想要实现的目标有解决方案吗?我感谢任何回应!public class WaitForActionProcess : IProcess{    public Action Finished { get; set; }    Action actionHandler;    public WaitForActionProcess(ref Action action)    {        actionHandler = action;    }    public void Play()    {        actionHandler += RaiseFinished;    }    public void RaiseFinished()    {        actionHandler -= RaiseFinished;        if(Finished != null)        {            Finished();        }    }}使用示例:public class ReturnToMainMenuFrame : TutorialEventFrame{    [SerializeField]    TutorialDialogueData dialogueData;    [SerializeField]    PointingArrowData arrowData;    [SerializeField]    TutorialDialogue tutorialDialogue;    [SerializeField]    PointingArrow arrow;    [SerializeField]    MainView mainView;    public override void StartFrame()    {        frameProcesses.Add(new ShowPointToUIProcess(arrow, arrowData));        frameProcesses.Add(new ShowDialogueProcess(tutorialDialogue, dialogueData));        frameProcesses.Add(new WaitForActionProcess(ref mainView.OnViewShown));        frameProcesses.Add(new HideDialogueProcess(tutorialDialogue, this));        frameProcesses.Add(new HidePointToUIProcess(arrow,this));        base.StartFrame();    }}
查看完整描述

2 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

简答

c# - 如何制作指向另一个动作的动作?


你不能。动作是委托,委托是不可变的。


应该指向我想听的动作的动作似乎实际上并没有指向它。


那是因为delegates是不可变的。即使您传递了一个ref委托,当您执行分配时,您也会创建一个副本。代表strings就是这样。


public WaitForActionProcess(ref Action action)

{

    // assignment creates a copy of a delegate

    actionHandler = action;

}

例子

这是为您准备的小提琴,可以进一步演示。


public class Program

{

    static Action action1;

    static Action actionHandler;

    public static void Main()

    {

        WaitForActionProcess(ref action1);

    }


    public static void WaitForActionProcess(ref Action action)

    {

        // this is still a reference to action1

        action += Both;


        // assignment creates a copy of a delegate

        actionHandler = action;


        // action is still a reference to action1

        // but actionHandler is a *copy* of action1

        action += OnlyAction1;

        actionHandler += OnlyActionHandler;


        action();

        // Both

        // OnlyAction1


        actionHandler();

        // Both

        // OnlyAction2

    }


    public static void Both()=> Console.WriteLine("Both");

    public static void OnlyAction1() => Console.WriteLine("OnlyAction1");

    public static void OnlyActionHandler() => Console.WriteLine("OnlyActionHandler");

}

可能的解决方法

使用 aList<Action>代替。这是一个 Fiddle。


using System;

using System.Collections.Generic;


public class Program

{

    static List<Action> action1 = new List<Action>();

    static List<Action> actionHandler;

    public static void Main()

    {

        WaitForActionProcess(action1);

    }


    public static void WaitForActionProcess(List<Action> action)

    {

        action.Add(Both);


        // assignment passes a reference to the List

        actionHandler = action;


        action.Add(OnlyAction1);

        actionHandler.Add(OnlyActionHandler);


        // now things work nicely

        foreach(var a in action) a();

        foreach(var a in actionHandler) a();

    }


    public static void Both()=> Console.WriteLine("Both");

    public static void OnlyAction1() => Console.WriteLine("OnlyAction1");

    public static void OnlyActionHandler() => Console.WriteLine("OnlyActionHandler");

}


查看完整回答
反对 回复 2021-07-31
  • 2 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信