0

I'm trying to write a simple method to make the code a little more readable. I'm writing a part where i have async tasks so I'm using Action as parameter of my methods to give the possibility to get a callback when the methods has finished.

In short my signatures always are like that:

public void myAsyncMethod(...params..., Action<other params> onFinish = null)

I use the default of Action as null only to give a little more flexibility to the library users, but in my implementations I have always to write this piece of code:

if (onFinish != null)
{
    UnityMainThreadDispatcher.Instance().Enqueue(
        () => onFinish(other params)
    );
}

This is because in unity I give the possibility to launch the Action on the main thread in case the user need to interact with the graphic cycle. My idea is that: can I put that piece of code in a method to leave the method implementation a little more readable? It would be really great to invoke that thing in a way like that:

onFinish?.InvokeOnMainThread(other params);

a little like the Action?.Invoke way. So I've done a little search about Extension Methods, Action and Generics in c# but I can't get a grasp to build a method with generics to do what I'm trying to reach. I really don't know what to search to reach my goal, I've looked around but probably I'm not good enough to put the concepts together to reach my target.

So far i thought things like that (that don't work):

public static void InvokeOnMainThread(this Action<T1, T2>, T1 t1, T2 t2){ ... }
public static void InvokeOnMainThread<Action, T1, T2>(Action<T1, T2>, T1 t1, T2 t2){ ... }

I've used Action with 2 parameters only because is the most common in my case, but I need the same call with 0 to 4 parameters (but I think that when I can get a grasp of the concept it will be easily extended or at least I can replicate it for the number of parameter that I need).

dbc
  • 104,963
  • 20
  • 228
  • 340
Lumen
  • 43
  • 1
  • 1
  • 7
  • Please provide a [mcve]. Explain what that code does, how that's different from what you want. and what _specifically_ you need help with. The above is not clear at all. – Peter Duniho Feb 25 '21 at 19:18
  • You will need 5 separate extension methods corresponding to the 0-4 parameters case. See [Can I have a variable number of generic parameters?](https://stackoverflow.com/q/1612887) to which the answer is, basically, *no*. – dbc Feb 25 '21 at 19:38

1 Answers1

1

You will need to create separate extension methods for the 0-4 possible parameters, like so:

public static partial class UnityExtensions
{
    public static void InvokeOnMainThread(this Action onFinish)
    {
        if (onFinish != null) // Or throw ArgumentNullException() if you prefer
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish());
    }
    
    public static void InvokeOnMainThread<T1>(this Action<T1> onFinish, T1 t1)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1));
    }
    
    public static void InvokeOnMainThread<T1, T2>(this Action<T1, T2> onFinish, T1 t1, T2 t2)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2));
    }
    
    public static void InvokeOnMainThread<T1, T2, T3>(this Action<T1, T2, T3> onFinish, T1 t1, T2 t2, T3 t3)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2, t3));
    }
    
    public static void InvokeOnMainThread<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> onFinish, T1 t1, T2 t2, T3 t3, T4 t4)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2, t3, t4));
    }
}

And then you would be able to do:

onFinish?.InvokeOnMainThread(param1, param2); // Or however many parameters you have.

As explained in Can I have a variable number of generic parameters?, c# does not allow for variable numbers of generic parameters. This is why e.g. there are distinct Tuple.Create<>() methods for each supported number of parameters.

dbc
  • 104,963
  • 20
  • 228
  • 340