How to return value from Action()?

In regards to the answer for this question Passing DataContext into Action(), how do I return a value from action(db)?

SimpleUsing.DoUsing(db => { 
// do whatever with db 
}); 

Should be more like:

MyType myType = SimpleUsing.DoUsing<MyType>(db => { 
// do whatever with db.  query buit using db returns MyType.
}); 

Solution 1:

You can use Func<T, TResult> generic delegate. (See MSDN)

Func<MyType, ReturnType> func = (db) => { return new MyType(); }

Also there are useful generic delegates which considers a return value:

  • Converter<TInput, TOutput> (MSDN)
  • Predicate<TInput> - always return bool (MSDN)

Method:

public MyType SimpleUsing.DoUsing<MyType>(Func<TInput, MyType> myTypeFactory)

Generic delegate:

Func<InputArgumentType, MyType> createInstance = db => return new MyType();

Execute:

MyType myTypeInstance = SimpleUsing.DoUsing(
                            createInstance(new InputArgumentType()));

OR explicitly:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());

Solution 2:

Your static method should go from:

public static class SimpleUsing
{
    public static void DoUsing(Action<MyDataContext> action)
    {
        using (MyDataContext db = new MyDataContext())
           action(db);
    }
}

To:

public static class SimpleUsing
{
    public static TResult DoUsing<TResult>(Func<MyDataContext, TResult> action)
    {
        using (MyDataContext db = new MyDataContext())
           return action(db);
    }
}

This answer grew out of comments so I could provide code. For a complete elaboration, please see @sll's answer below.

Solution 3:

You can also take advantage of the fact that a lambda or anonymous method can close over variables in its enclosing scope.

MyType result;

SimpleUsing.DoUsing(db => 
{
  result = db.SomeQuery(); //whatever returns the MyType result
}); 

//do something with result

Solution 4:

Use Func<T> rather than Action<T>.

Action<T> acts like a void method with parameter of type T, while Func<T> works like a function with no parameters and which returns an object of type T.

If you wish to give parameters to your function, use Func<TParameter1, TParameter2, ..., TReturn>.