Wie kann ich einen Wert von Action () zurückgeben?

92

Wie kann ich in Bezug auf die Antwort auf diese Frage, die DataContext in Action () übergibt , einen Wert aus action (db) zurückgeben?

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

Sollte eher so sein:

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

Antworten:

97

Ihre statische Methode sollte gehen von:

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

Zu:

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

Diese Antwort entstand aus Kommentaren, damit ich Code bereitstellen konnte. Eine vollständige Ausarbeitung finden Sie in der Antwort von @ sll unten.

Kirk Woll
quelle
113

Sie können einen Func<T, TResult>generischen Delegaten verwenden. (Siehe MSDN )

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

Es gibt auch nützliche generische Delegaten, die einen Rückgabewert berücksichtigen:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- immer bool ( MSDN ) zurückgeben

Methode:

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

Generischer Delegierter:

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

Ausführen:

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

ODER explizit:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
quelle
Richtig - können Sie ein Beispiel dafür geben, wie die Methode aussehen sollte?
4. Raum
5
@LB - Leute zu googeln ist nicht konstruktiv. SO existiert, um vollständige Antworten zu liefern.
Kirk Woll
5
@ KirkWoll Aber die Antwort gibt die Zutaten , es muss nicht gekocht werden
LB
9
@LB - es ist besser, wenn es vollständig ist. Ich finde deine Analogie falsch.
Kirk Woll
1
@LB, besser nicht kommentieren, da Sie überhaupt keinen Wert hinzufügen.
4. Raum
15

Sie können auch die Tatsache nutzen, dass ein Lambda oder eine anonyme Methode Variablen in ihrem umschließenden Bereich schließen kann.

MyType result;

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

//do something with result
Steve Rowbotham
quelle
Ja, das nennt man Closure (funcitonal language stuff, das auch für uns verfügbar ist)
sll
3

Verwenden Sie Func<T>eher als Action<T>.

Action<T>verhält sich wie eine void-Methode mit Parametern vom Typ T, während sie Func<T>wie eine Funktion ohne Parameter funktioniert und ein Objekt vom Typ T zurückgibt.

Wenn Sie Ihrer Funktion Parameter zuweisen möchten, verwenden Sie Func<TParameter1, TParameter2, ..., TReturn>.

Ulysses Alves
quelle