Jak zwrócić wartość z Action ()?

96

W odniesieniu do odpowiedzi na to pytanie Przekazywanie DataContext do Action () , w jaki sposób mogę zwrócić wartość z akcji (db)?

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

Powinien być bardziej podobny do:

MyType myType = SimpleUsing.DoUsing<MyType>(db => { 
// do whatever with db.  query buit using db returns MyType.
}); 
4thSpace
źródło

Odpowiedzi:

101

Twoja metoda statyczna powinna pochodzić z:

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

Do:

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

Ta odpowiedź wyrosła z komentarzy, więc mogłem podać kod. Aby uzyskać pełne omówienie, zobacz odpowiedź @ sll poniżej.

Kirk Woll
źródło
115

Możesz użyć Func<T, TResult>ogólnego delegata. (Zobacz MSDN )

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

Istnieją również przydatne delegaty ogólne, które uwzględniają wartość zwracaną:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- zawsze zwraca bool ( MSDN )

Metoda:

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

Delegat ogólny:

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

Wykonać:

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

LUB wyraźnie:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
źródło
6
@LB - proszenie ludzi o wygooglowanie nie jest konstruktywne. SO istnieje, aby udzielić pełnych odpowiedzi.
Kirk Woll
5
@KirkWoll Ale odpowiedź podaje składniki , nie musi być ugotowany
LB
9
@LB - lepiej, żeby był kompletny. Uważam, że twoja analogia jest fałszywa.
Kirk Woll
1
@LB, lepiej nie komentować, ponieważ nie dodajesz żadnej wartości.
4th Space
1
@Shn_Android_Dev - masz rację, ale Action nie jest narzędziem do zwracania wartości, z pewnością możemy obrócić i odkryć koło na nowo, ale czy taka komplikacja kodu jest warta trzymania się głównie Action?
2017
15

Można również skorzystać z faktu, że metoda lambda lub metoda anonimowa może zamykać zmienne w otaczającym jej zakresie.

MyType result;

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

//do something with result
Steve Rowbotham
źródło
tak, to się nazywa Zamknięcie (funkcjonalny język językowy, który jest również dostępny dla nas)
sll
4

Użyj Func<T>zamiast Action<T>.

Action<T>działa jak metoda void z parametrem typu T, podczas gdy Func<T>działa jak funkcja bez parametrów i zwraca obiekt typu T.

Jeśli chcesz nadać parametry swojej funkcji, użyj Func<TParameter1, TParameter2, ..., TReturn>.

Ulysses Alves
źródło