Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous delegate as function parameter

Tags:

I'm trying to pass parameter, which is anonymous delegate (no input parameters, no return value), to function.

Something like this:

private function DoSomething(delegate cmd) {      cmd(); } 

Then, I'm want to use this function to call function in this way:

DoSomething(delegate {      Console.WriteLine("Hooah!"); }); 

I'm want this specific way, because it's easy to use writing style.

Possible?

like image 625
No1Lives4Ever Avatar asked Feb 15 '14 09:02

No1Lives4Ever


Video Answer


1 Answers

Exactly for such purposes Microsoft has created the Action and Func wrapper classes in the .NET framework. Both classes are relying on anonymous functions. Use Action if you don't need to return any result, just to execute the anonymous function:

private void DoSomething(Action action) {     action(); } 

It can be used like this:

DoSomething(() =>  {     Console.WriteLine("test"); }); 

The () => term is a lambda expression and means something like input with no parameters is calling .... See the documentation for a thorough explanation.

If you want to return a result, then use the Func delegate:

private T DoSomething<T>(Func<T> actionWithResult) {     return actionWithResult(); } 

Usage:

Console.WriteLine(DoSomething<int>(() =>  {     return 100; })); 

Both wrappers have overrides that accept up to 8 parameters.

When using Func, the last parameter is always the return type:

// returns a string Func<string> t = () => { return "test string"; }; // first parameter is of type int, result of type string Func<int, string> toString = (id) => { return id.ToString(); }; // parameters are of type int and float, result is string Func<int, float, string> sumToString = (n1, n2) => { return (n1 + n2).ToString(); }; 

The Func wrapper can be used directly with a typed parameter:

Func<string, string> up = text => text.ToUpper(); Console.WriteLine(up("test")); 

I often use Func's in order to create a generic executor that is wrapped in a try/catch block and logging if something happens. This way i reduce the repetative code:

private T safeCallWithLog<T>(Func<T> action) {     try     {                    return action();     }     catch (Exception ex)     {         Console.WriteLine(String.Format("Oops ...: {0}", ex.Message));     }     // return default type if an error occured     return default(T); } 

Usage:

var result = safeCallWithLog<DbEntry>(() =>             {                 return databaseContext.GetEntryWithId(42);             });  var id = safeCallWithLog<int>(() =>                     {                         return databaseContext.GetIdFor("J.D.");                     });  

You could still use the original delegate concept. The Action and the Func classes are just wrappers around predefined generic delegate methods.

// declare delegate contract private delegate void output(); // create caller method private void method(output fun) {     fun(); } // some test functions, that must match exactly the delegate description // return type and number of arguments private void test1() {     Console.WriteLine("1"); }  private void test2() {     Console.WriteLine(DateTime.Now.ToString()); }  // call different methods method(test1); method(test2); // inline call without hard coded method method(delegate()  {     Console.WriteLine("inline"); }); 
like image 200
keenthinker Avatar answered Oct 18 '22 09:10

keenthinker