Comment retourner la valeur d'Action ()?

92

En ce qui concerne la réponse à cette question Passing DataContext into Action () , comment puis-je renvoyer une valeur de l'action (db)?

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

Devrait être plus comme:

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

Réponses:

97

Votre méthode statique doit aller de:

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

À:

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

Cette réponse est née des commentaires afin que je puisse fournir du code. Pour une élaboration complète, veuillez consulter la réponse de @ sll ci-dessous.

Kirk Woll
la source
113

Vous pouvez utiliser Func<T, TResult>un délégué générique. (Voir MSDN )

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

Il existe également des délégués génériques utiles qui prennent en compte une valeur de retour:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- renvoie toujours booléen ( MSDN )

Méthode:

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

Délégué générique:

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

Exécuter:

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

OU explicitement:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
la source
Droite - pouvez-vous donner un exemple de ce à quoi devrait ressembler la méthode?
4thSpace
5
@LB - demander aux gens de google n'est pas constructif. SO existe pour fournir des réponses complètes.
Kirk Woll
5
@KirkWoll Mais la réponse donne les ingrédients , il n'a pas été cuit
LB
9
@LB - il vaut mieux que ce soit complet. Je trouve votre analogie fausse.
Kirk Woll
1
@LB, mieux vaut ne pas commenter car vous n'ajoutez aucune valeur.
4thSpace
15

Vous pouvez également profiter du fait qu'une méthode lambda ou anonyme peut fermer des variables dans sa portée englobante.

MyType result;

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

//do something with result
Steve Rowbotham
la source
ouais, cela s'appelle Closure (langage fonctionnel qui est également disponible pour nous)
sll
4

Utilisez Func<T>plutôt que Action<T>.

Action<T> agit comme une méthode void avec un paramètre de type T, tandis que Func<T> fonctionne comme une fonction sans paramètres et qui renvoie un objet de type T.

Si vous souhaitez donner des paramètres à votre fonction, utilisez Func<TParameter1, TParameter2, ..., TReturn>.

Ulysse Alves
la source