dynamic delegate to pass a method as parameter in C#

10,182

Solution 1

You can use a simple Action

void AddMethod(Action action) //or void AddMethod(Func<TResult> fxn)
{
}

and call as

AddMethod(()=>Test(obj));   

or

AddMethod(()=>Test(obj1,obj2));   

--EDIT--

AddMethod(() => Math.Max(1,3));  
AddMethod(() => (int)Math.Sqrt(4));
AddMethod(() => new int[]{8,5,6}.Min())

void AddMethod(Func<int> fxn)
{
     int i = fxn() * fxn();  // <---
}

Solution 2

Since .NET doesn't allow delegates with an unknown parameter syntax (this would approximate C void pointers, which is not something you want in a type-safe language), the closest thing that allows a variable argument list would be to pass an array of object arguments (i.e. object MyMethod(params object[] args)).
However, since this array is also an object reference, you can suffice with a single object reference:

object MyMethod(object arg))

The .NET framework also does this, see e.g. the ParameterizedThreadStart delegate)

So the basic idea is that you require that the user writes his code as a method that matches the above signature, and in turn it can receive any variable list of arguments of any type or size.

Share:
10,182
Kamyar Nazeri
Author by

Kamyar Nazeri

Coder for life with expertise in C++, C#, Python, JavaScript, TypeScript, and most recently with a focus on Cloud, Deep Learning in Computer Vision, and Generative Models. Homepage: knazeri.github.io Twitter: @knazeri LinkedIn: kamyar nazeri GitHub: github.com/knazeri

Updated on June 24, 2022

Comments

  • Kamyar Nazeri
    Kamyar Nazeri about 2 years

    Is there any way to use DLR to reference a method in C#?

    In dynamic languages like JavaScript or Python I could easily pass a method as an argument to another method. In C# being statically typed language, I either use Delegate type which needs lots of casting:

    public static void AddMethod(Delegate del)
    {
        // implementation
    }
    

    and then use casting whenever I call this method

    static void Main(string[] args)
    {
        AddMethod(new Func<object, bool>(Test));
    }
    
    public static bool Test(object obj)
    {
        return true;
    }
    

    Or, I need to define dozens of overloads to satisfy any method calls:

    public static void AddMethod<TResult>(Func<TResult> method)
    {
    }
    
    public static void AddMethod<T, TResult>(Func<T, TResult> method)
    {
    }
    
    public static void AddMethod<T1, T2, TResult>(Func<T1, T2, TResult> method)
    {
    }
    
    public static void AddMethod<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> method)
    {
    }
    

    Is there any cleaner way to define an argument as a placeholder for all other methods? (I'm trying to avoid MethodInfo or other Reflection stuff here)

    I was trying something like this:

    public delegate dynamic DynamicDelegate(params dynamic[] args);
    
    public static void AddMethod(DynamicDelegate method)
    {
    }
    

    But the compiler doesn't seem to accept a statically typed method for a dynamically declared delegates!

    Any other thoughts?