簡體   English   中英

Unity C# 動作代表 - 如何創建列表<action>具有不同的參數類型?</action>

[英]Unity C# Action Delegates - How to Create List<Action> with different parameter types?

我希望在這里得到一些幫助(我是C#Unity的新手)。

我想創建一個Action List ,我最終可以在OnDestroy生命周期方法調用期間循環並清除/取消它。

Anyhoo,我將在下面標記我想要實現的目標以及錯誤是什么:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Game : MonoBehaviour
{
    // Action delegate
    public static Action OnEvent1;
    public static Action<int> OnEvent2;
    public static Action<Vector2> OnEvent3;
    public static Action<Vector2> OnEvent4;
    public static Action OnEvent5;
    public static Action<bool> OnEvent6;

    private List<Action> ActionListToClear = new List<Action>() {
        OnEvent1, // all good
        OnEvent2, // Error as Action<int> is not Action
        OnEvent3, // Error as Action<Vector2> is not Action
        OnEvent4, // Error as Action<Vector2> is not Action
        OnEvent5, // all good
        OnEvent6  // Error as Action<bool> is not Action
    };

    ....

    private void OnDestroy()
    {
        foreach (Action action in ActionListToClear )
        {
            action = null;
        }
    }
};

我還嘗試在List中實現泛型類型:

private List<Action<T>> ActionList = new List<Action<T>() { OnEvent1, OnEvent2... etc. };

但這會導致:

The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

有誰知道創建具有不同Action類型的List<Action>的最佳方法? 即帶參數和不帶參數? 謝謝!

我要試一試。 您問題下的所有評論都很棒。 你必須以更加面向對象的方式思考。 這里有一個關於如何完成你想要的東西的想法,也許會讓你跳出框框思考更多。 無論如何,我並不是說你應該這樣做。 只是對您可以使用的東西的想法。

所以你定義了一個接口,這是所有“Action”對象的共同點。 你在你的問題中說你只是想要一種“銷毀”它們的方法,所以我們將強制實現它的任何東西也實現Destory()

public interface IAction
{
    void Destroy();
}

現在我們創建一個“基礎”動作,它可以執行 1 個參數,該參數具有Destroy應該執行的默認實現:

public abstract class BaseAction<T> : IAction
{
    public Action<T> Action { get; protected set; }
    public virtual void Destroy()
    {
        Action = null;
    }
}

現在我們創建另一個“基礎”動作,它可以執行 0 個參數,該動作具有Destroy應該執行的默認實現:

public abstract class BaseAction : IAction
{
    public Action Action { get; protected set; }

    public virtual void Destroy()
    {
        Action = null;
    }
}

然后我們創建我們的實際事件:

public class Event6 : BaseAction<bool>
{
    public Event6()
    {
        Action = new Action<bool>(x =>
            Console.WriteLine($"I just executed Event 6 with {x}"));
    }
}

public class Event7 : BaseAction
{
    public Event7()
    {
        Action = new Action(() =>
            Console.WriteLine("I just executed Event 7"));
    }

    public override void Destroy()
    {
        // do something special here
        base.Destroy();
    }
}

public class Event8 : BaseAction<int>
{
    public Event8()
    {
        Action = new Action<int>(x =>
            Console.WriteLine($"I just executed Event 8 with {x}"));
    }
}

現在我們可以創建我們想要的所有事件

private Event6 _ev6 = new Event6();
private Event7 _ev7 = new Event7();
private Event8 _ev8 = new Event8();

public void Main(string[] args)
{
    // how you'd call the actions:
    _ev7.Action.Invoke();
    _ev6.Action.Invoke(true);

    // now remember, the `Action` member could be null if they were Destroyed... see below

    // you can then create an array of them because they all have "IAction" in common
    var lst = new List<IAction> { _ev6, _ev7, _ev8 };

    // you can also iterate over them and destroy them.
    lst.ForEach(x => x.Destroy());  
}

正如幾位好心的海報所指出的那樣,將我的所有Actions添加到List以在OnDestroy期間循環的方法可能會使問題過於復雜。

相反,以下方法可以解決問題:

private void OnDestroy()
{
    OnEvent1 = null;
    OnEvent2 = null;
    OnEvent3 = null;
    ...etc.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM