¿Cómo devolver el valor de Action ()?

92

Con respecto a la respuesta para esta pregunta Pasando DataContext a Action () , ¿cómo devuelvo un valor de action (db)?

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

Debería ser más como:

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

Respuestas:

97

Tu método estático debe ir de:

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

A:

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

Esta respuesta surgió de los comentarios para que pudiera proporcionar código. Para una elaboración completa, consulte la respuesta de @ sll a continuación.

Kirk Woll
fuente
113

Puede utilizar Func<T, TResult>delegado genérico. (Ver MSDN )

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

También hay delegados genéricos útiles que consideran un valor de retorno:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- siempre devuelve bool ( MSDN )

Método:

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

Delegado genérico:

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

Ejecutar:

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

O explícitamente:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
fuente
Bien, ¿puede dar un ejemplo de cómo debería ser el método?
4thSpace
5
@LB: pedirle a la gente que busque en Google no es constructivo. SO existe para proporcionar respuestas completas.
Kirk Woll
5
@KirkWoll Pero la respuesta da los ingredientes , no tiene que ser cocinado
LB
9
@LB: es mejor que esté completo. Encuentro su analogía falsa.
Kirk Woll
1
@LB, mejor no comentar, ya que no está agregando ningún valor.
4thSpace
15

También puede aprovechar el hecho de que un método lambda o anónimo puede cerrar las variables en su ámbito adjunto.

MyType result;

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

//do something with result
Steve Rowbotham
fuente
sí, esto se llama cierre (material de lenguaje funcional que también está disponible para nosotros)
sll
4

Utilice en Func<T>lugar de Action<T>.

Action<T>actúa como un método vacío con parámetro de tipo T, mientras que Func<T>funciona como una función sin parámetros y que devuelve un objeto de tipo T.

Si desea darle parámetros a su función, use Func<TParameter1, TParameter2, ..., TReturn>.

Ulysses Alves
fuente