Como retornar o valor de Action ()?


92

Com relação à resposta a esta pergunta Passing DataContext into Action () , como faço para retornar um valor de action (db)?

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

Deve ser mais como:

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

Respostas:


97

Seu método estático deve ir de:

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

Para:

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

Essa resposta surgiu de comentários para que eu pudesse fornecer o código. Para uma elaboração completa, consulte a resposta de @sll abaixo.


113

Você pode usar Func<T, TResult>delegado genérico. (Veja MSDN )

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

Além disso, existem delegados genéricos úteis que consideram um valor de retorno:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- sempre retorna bool ( MSDN )

Método:

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

Delegado genérico:

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

Executar:

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

OU explicitamente:

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

Certo - você pode fornecer um exemplo de como o método deve ser?
— 4º Espaço de

5
@LB - pedir às pessoas que pesquisem no Google não é construtivo. O SO existe para fornecer respostas completas.
— Kirk Woll

5
@KirkWoll Mas a resposta dá os ingredientes , não precisa ser cozido
— LB

9
@LB - é melhor que seja completo. Acho sua analogia espúria.
— Kirk Woll

1
@LB, melhor não comentar, já que você não está agregando valor algum.
— 4º Espaço de

15

Você também pode tirar vantagem do fato de que um método lambda ou anônimo pode fechar as variáveis ​​em seu escopo envolvente.

MyType result;

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

//do something with result

sim, isso é chamado de Encerramento (coisas linguagem funcitonal que está disponível para nós também)
— SLL

4

Use em Func<T>vez de Action<T>.

Action<T>atua como um método void com parâmetro do tipo T, enquanto Func<T>funciona como uma função sem parâmetros e que retorna um objeto do tipo T.

Se você deseja dar parâmetros à sua função, use Func<TParameter1, TParameter2, ..., TReturn>.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.