如何从Action()返回值?

时间:2011-11-11 20:35:35

标签: c# .net linq

关于这个问题Passing DataContext into 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.
}); 

5 个答案:

答案 0 :(得分:100)

您可以使用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());

答案 1 :(得分:76)

你的静态方法应该来自:

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答案。

答案 2 :(得分:12)

您还可以利用lambda或匿名方法可以关闭其封闭范围内的变量这一事实。

MyType result;

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

//do something with result

答案 3 :(得分:0)

使用Func<T>而不是Action<T>

"Action<T>"的作用类似于带有T类型参数的void方法,而"Func<T>"的作用类似于没有参数的函数,并且返回类型为T的对象。如果希望为函数提供参数,请使用Func<TReturn, TParameter>

答案 4 :(得分:-1)

我也有这个需求,但涉及跨线程问题 - MainForm 中的方法从 UserControl 中的控件返回数据。 Original code was an extension method that perform an Action;后来,我需要返回一个值,正如@sll 建议的那样,不得不改用 Func 委托。

在 ControlExtensions 类中:

     public static TResult RunOnUiThread<TResult>(this Control @this, Func<TResult> code)
        {
            if (@this.InvokeRequired)
            {
                var toReturn = @this.BeginInvoke(code);                  
                return (TResult)@this.EndInvoke(toReturn);
            }
            else
            {
                return code.Invoke();
            }
       }

这个扩展方法是从 MainForm 中的一个方法中调用的,从 UserControl 中的一个控件中获取一些值;在这个例子中,我从 ListBox 返回 SelectedItem 的值:

                return UserControl1.listBox1.RunOnUiThread(
                    () => UserControl1.listBox1.GetItemText(
                            UserControl1.listBox1.SelectedItem)
                    );