65.9K
CodeProject is changing. Read more.
Home

Passing Delegates With Any Signature to a Method

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.36/5 (6 votes)

Jul 17, 2015

CPOL
viewsIcon

13121

A simple tip to pass a delegate with any signature to a method

Introduction

This is a simple trick to pass a delegate with any signature to another method to consume it.

Using the Code

Before I go further with this, I just want to thank Andreas Gieriet, one of the forum members for his help with this.

If we use the closure concept of lambda expressions, we don't actually even have to pass parameters other than the anonymous delegates themselves.

The following two wrappers cater for Action and Func...

public static TReturn FuncWrapper<TReturn>(Func<TReturn> function)
{
   Console.WriteLine("FUNCTION: Common code before method logic");
   TReturn result = function();
   Console.WriteLine("FUNCTION: Common code after method logic");
   return result;
}

public static void ActionWrapper(Action method)
{
    Console.WriteLine("ACTION: Common Code before method logic.");
    method();
    Console.WriteLine("ACTION: Common Code after method logic.");
}

... and can be called as follows:

private static void Main(string[] args)
{    
    DateTime dateOfBirth = new DateTime(1994, 12, 25);
    string shortDate = dateOfBirth.ToShortDateString();
    
    // We can pass a function with any signature to the function wrapper like this.
    int x = 1;
    int y = 2;
    int z = FuncWrapper<int>(() => SumTwoIntegers(x, y));
    Console.WriteLine(string.Format("The sum of {0} and {1} is {2}.", x, y, z));

    Console.WriteLine();

    // We can declare and execute an inline function and pass it to the function wrapper like this:
    string calcAgeResult = FuncWrapper<string>(() => 
    {
        Console.WriteLine(string.Format("Calculating age for date of birth {0}.", shortDate));
        int ageInYears = (int)(DateTime.Now.Subtract(dateOfBirth).TotalDays/365.25);
        return string.Format("Someone born on {0} is {1} years old.", 
            shortDate, ageInYears);
    });
    Console.WriteLine(calcAgeResult);
    
    Console.WriteLine();
    
    // We can pass some ad hoc code to the action wrapper like this
    ActionWrapper(()=> {
        Console.WriteLine(string.Format("INSIDE VOID: Date of birth previously used was {0}", 
            dateOfBirth.ToShortDateString()));
    });
}

public static int SumTwoIntegers(int x, int y)
{
    Console.WriteLine("Inside the SumTwoIntegers() method");
    return x + y;
}

This will produce the following output:

FUNCTION: Common code before method logic
Inside the SumTwoIntegers() method
FUNCTION: Common code after method logic
The sum of 1 and 2 is 3.

FUNCTION: Common code before method logic
Calculating age for date of birth 25/12/1994.
FUNCTION: Common code after method logic
Someone born on 25/12/1994 is 20 years old.

VOID: Common Code before method logic.
INSIDE VOID: Date of birth previously used was 25/12/1994
VOID: Common Code after method logic.

Points of Interest

The nice thing with this implementation is that you can use variables from the calling method in the closures as they close over them. The variables are shared. We just have to be careful how we use the shared variables so that we don't unintentionally change them.

History

  • 15th July, 2015 - Initial article
  • 17th July, 2015 - Simplified, and downgraded to tip
  • 19h July, 2015 - Further simplification