Как вернуть значение из Action ()?

95

Что касается ответа на этот вопрос, передавая DataContext в Action () , как мне вернуть значение из действия (db)?

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

Должно быть больше похоже:

MyType myType = SimpleUsing.DoUsing<MyType>(db => { 
// do whatever with db.  query buit using db returns MyType.
}); 
4thSpace
источник

Ответы:

100

Ваш статический метод должен идти от:

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);
    }
}

Этот ответ вырос из комментариев, поэтому я мог предоставить код. Для более подробной информации см. Ответ @ sll ниже.

Кирк Уолл
источник
114

Вы можете использовать Func<T, TResult>общий делегат. (См. MSDN )

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

Также есть полезные универсальные делегаты, которые рассматривают возвращаемое значение:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- всегда возвращать bool ( MSDN )

Метод:

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

Общий делегат:

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

Выполнить:

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

ИЛИ явно:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
источник
6
@LB - просить людей гуглить неконструктивно. SO существует, чтобы дать полные ответы.
Кирк Уолл
5
@KirkWoll Но в ответе указаны ингредиенты , их еще не готовили
LB
9
@LB - лучше, чтобы он был полным. Я считаю вашу аналогию ложной.
Кирк Уолл
1
@LB, лучше не комментировать, потому что вы не добавляете никакой ценности.
4thSpace
1
@Shn_Android_Dev - вы правы, но Action - это не средство для возврата значения, конечно, мы можем развернуться и изобрести колесо, но стоит ли такое усложнение кода в основном придерживаться Action?
sll 02
15

Вы также можете воспользоваться тем фактом, что лямбда- или анонимный метод может закрывать переменные в своей охватывающей области.

MyType result;

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

//do something with result
Стив Роуботэм
источник
да, это называется Closure (функциональный языковой материал, который также доступен для нас)
sll
4

Используйте, Func<T>а не Action<T>.

Action<T>действует как метод void с параметром типа T, а Func<T>работает как функция без параметров и возвращает объект типа T.

Если вы хотите передать параметры своей функции, используйте Func<TParameter1, TParameter2, ..., TReturn>.

Улисс Алвес
источник