Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic delegate to pass a method as parameter in C#

Tags:

c#

dynamic

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?

like image 353
Kamyar Nazeri Avatar asked Nov 24 '12 11:11

Kamyar Nazeri


People also ask

Can we pass delegate as parameter?

Because the instantiated delegate is an object, it can be passed as an argument, or assigned to a property. This allows a method to accept a delegate as a parameter, and call the delegate at some later time.

How do you write a delegate to an int parameter?

Example: // "public" is the modifier // "int" is return type // "GeeksForGeeks" is delegate name // "(int G, int F, int G)" are the parameters public delegate int GeeksForGeeks(int G, int F, int G); Note: A delegate will call only a method which agrees with its signature and return type.

Which type of delegate will you choose if you want to declare a method that accepts an integer as a parameter and returns an integer?

The myDelegate is a user-defined name of the delegate that takes a single integer parameter and returns an integer value. Therefore, the myDelegate references and invokes a method that takes a single integer parameter and returns an integer value.

Can I pass method as parameter C#?

In C#, we can also pass a method as a parameter to a different method using a delegate. We use the delegate keyword to define a delegate. Here, Name is the name of the delegate and it is taking parameter. Suppose we have a delegate having int as the parameter.


2 Answers

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();  // <---
}
like image 104
L.B Avatar answered Oct 12 '22 22:10

L.B


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.

like image 38
Leon Bouquiet Avatar answered Oct 12 '22 23:10

Leon Bouquiet