Reputation: 598
I'm hoping for some help here (I'm new to C#
and Unity
).
I want to create a List
of Action
s that I can eventually loop over and clear / nullify during the OnDestroy
lifecycle method call.
Anyhoo, I'll mark below what I'm trying to achieve and what the errors are:
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;
}
}
};
I've also tried implementing a generic type into the List
:
private List<Action<T>> ActionList = new List<Action<T>() { OnEvent1, OnEvent2... etc. };
but that results in:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
Does anyone know the best way to create a List<Action>
with different Action
types? I.e. with and without parameters? Thanks!
Upvotes: 1
Views: 4623
Reputation: 598
As a couple of kindly posters pointed out, the approach of adding all my Actions
to a List
to loop over during OnDestroy
likely over-complicates the issue.
Instead the following does the trick:
private void OnDestroy()
{
OnEvent1 = null;
OnEvent2 = null;
OnEvent3 = null;
...etc.
}
Upvotes: 0
Reputation: 13557
I'm going to take a stab at this. All the comments under your question are great. You have to think in a more object-oriented way. Here is an idea on how you could accomplish what you want and maybe get you thinking more outside the box. I'm not saying this is how you should do it, by any means. Just an idea of something you could work with.
So you define an interface, this is what all "Action" objects will have in common. You say in your question you just want a way to "Destroy" them, so we will force anything that implements it to also implement Destory()
public interface IAction
{
void Destroy();
}
Now we create a "Base" action that can do 1 parameter that has a default implementation of what Destroy
should do:
public abstract class BaseAction<T> : IAction
{
public Action<T> Action { get; protected set; }
public virtual void Destroy()
{
Action = null;
}
}
Now we create another "Base" action that can do 0 parameters that has a default implementation of what Destroy
should do:
public abstract class BaseAction : IAction
{
public Action Action { get; protected set; }
public virtual void Destroy()
{
Action = null;
}
}
Then we create our actual events:
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}"));
}
}
Now we can create all the events we want
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());
}
Upvotes: 1