Anonymous 1317
I have a list of nine functions with different signatures, which have to be passed to another object.
I can't use
```
List<Action> callbacks = new List<Action>();
```
or any of its variants, or
```
List<Func<T>> callbacks = new List<Func<T>>();
```
because the functions have different signatures.
I tried an Object[], and got "Cannot convert method group "myFunction" to non-delegate type "Object".
Is it even possible?
Top Answer
Josh Darnell
There are technically a couple of ways to do this by using the `dynamic` keyword. This allows you to create a list of delegates that are all of different "types."
Each of the approaches uses a class with three static methods, which are used in the list:
- one that takes no arguments and returns a string
- one that takes one argument and returns a string
- one that takes two arguments and returns a bool
The first approach defines the arguments being passed to the functions when creating the list - the code that receives the list just needs to call each function, and potentially handle the return values as appropriate.
::: tio nZHBT8MgFMbv/BUvPUGcvXiz6xKzqJctGjXxYDwwii0JhQbolsb0b6@0pXNzxiW@C3nw/T7ge8xeMsu6rrZC5fDcWMfLBB128VJLyZkTWtn4nituBEsQYpJaC49G54aW6BOBL@uoEwy2WmSwpkJh64w3ensHanJLBs2o7GslrJtnjaKlYAsouSt0ZiEFxXfHZ/iK@AsnLAjjmyzDvfSuVmw@XrTAmEC6gHWQvBR@ExPi8X/TkVY8Om@x0Vr@YTCDyO306LM3@tCGU1YA3lITXEGoyZ/sdd@R9bX0c9CSx69GOL4SiuPooXZV7a4hgotA48MHt@gn@8RpNqBB1aIWoareSD@9MMRxvuErYb7HijE1CCH3Hx934tuyck1yjgiNT2dg/fob0ud6AswmJ5/pBEOa9m2C2q77Ag
§§§ cs cs-csc
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<dynamic> methods = new List<dynamic>(3);
methods.Add(new Func<string>(() => Methods.Thing()));
methods.Add(new Func<string>(() => Methods.Thing("one")));
methods.Add(new Func<bool>(() => Methods.Thing("one", "two")));
foreach (var method in methods)
{
Console.WriteLine("Output: " + method());
}
Console.ReadLine();
}
}
public static class Methods
{
public static string Thing() => string.Empty;
public static string Thing(string one) => one;
public static bool Thing(string one, string two) => one == two;
}
§§§
``` none
Output:
Output: one
Output: False
Microsoft (R) Build Engine version 16.3.0-ci for Mono
Copyright (C) Microsoft Corporation. All rights reserved.
```
:::
The second approach allows the code that iterates through the list to pass in arguments. This is tricky, as the calling code will need to know what the arguments are, otherwise a runtime error will occur if the wrong type / number of arguments are passed:
::: tio rZFNa8MwDIbv/hUiJ4d1YR@3pQmMsu3SssEGO5QcXMekBscOtrMSRn575iROaWlhZcwXI@t9JEsvNdfU0K6rDZcFvDfGsjJGh1G0UEIwarmSJnphkmlOY4SoIMbAm1aFJiX6RuCOscRyCl@K57AiXGJjtSu0zoDowoSDZlT2Z8mNneeNJCWnKZTMblVuIAHJdsc5fB@6hhPmhdFjnuNe@lxLOh8bpXjlkx9bF4YOu4CawX/QM9goJc7U2BdZuAUqwaJPzS1bcslw8FrbqrYPEMDV1GN9k@HD1hdStxkOlGTBH9A7j84gsDu1r9CiFqGq3gjnqDd29NxP6D0/Voy7gGF4HEKS@pfoqaxsE/9G@MD9ZmDdfQ7pF30CTD6Am2GCIUn6MEZt1/0A
§§§ cs cs-csc
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<dynamic> methods = new List<dynamic>(3);
methods.Add(new Func<string>(Methods.Thing));
methods.Add(new Func<string, string>(Methods.Thing));
methods.Add(new Func<string, string, bool>(Methods.Thing));
Console.WriteLine("Output: " + methods[0]());
Console.WriteLine("Output: " + methods[1]("one"));
Console.WriteLine("Output: " + methods[2]("one", "two"));
}
}
public static class Methods
{
public static string Thing() => string.Empty;
public static string Thing(string one) => one;
public static bool Thing(string one, string two) => one == two;
}
§§§
``` none
Output:
Output: one
Output: False
Microsoft (R) Build Engine version 16.3.0-ci for Mono
Copyright (C) Microsoft Corporation. All rights reserved.
```
:::
Generally, though, I agree with the comments - if you provide some detail about what your *goal* is, we might be able to suggest a more idiomatic C# solution. None of this feels all that natural in C#.