【问题标题】:Can I use params in Action or Func delegates?我可以在 Action 或 Func 代表中使用参数吗?
【发布时间】:2011-05-02 20:34:50
【问题描述】:

当我尝试在 Action 委托中使用参数时...

private Action<string, params object[]> WriteToLogCallBack;

我收到了这个设计时错误:

类、结构或接口成员声明中的标记“参数”无效

任何帮助!

【问题讨论】:

  • params 不是类型,即你可以在类型定义中使用ref

标签: c# delegates action params-keyword


【解决方案1】:

这个解决方法怎么样?

private Action<string, object[]> writeToLogCallBack;
public void WriteToLogCallBack(string s, params object[] args)
{
  if(writeToLogCallBack!=null)
    writeToLogCallBack(s,args);
}

或者您可以定义自己的委托类型:

delegate void LogAction(string s, params object[] args);

【讨论】:

  • 如何用 lambda 调用它?
【解决方案2】:

C# 中不能使用可变类型参数。

这就是为什么会有很多 Action&lt;...&gt;Func&lt;...&gt;Tuple&lt;...&gt; 的声明,例如。不过,这将是一个有趣的功能。 C++0x has them.

【讨论】:

  • 不确定它与泛型(相对于模板)的效果如何。
【解决方案3】:

你可以试试这个。它允许任意数量的参数,如果您传递错误数量或类型的参数,您将收到编译时错误。

public delegate T ParamsAction<T>(params object[] oArgs);

public static T LogAction<T>(string s, ParamsAction<T> oCallback)
{
    Log(s);
    T result = oCallback();
    return T;
}

Foo foo = LogAction<Foo>("Hello world.", aoArgs => GetFoo(1,"",'',1.1));

【讨论】:

  • 这是一个非常好的方法......干得好,先生
  • Bryan 这里有一段很棒的代码。我在上面的代码中添加了一个小扩展,以显示如何包装多个方法调用。我正在使用它将包含数据库调用的多个方法包装到一个事务中。谢谢布莱恩 :-)
  • 这应该返回结果而不是 T 吗?
  • 如果你做不到LogAction&lt;Foo&gt;("Hello world.", (p1,p2,p3) =&gt; GetFoo(p1,p2,p3));还有什么意义???减去....
【解决方案4】:

您可以在委托的实际声明中使用params,但不能在类型为 one 时使用。 Action 的泛型参数只是类型,而不是调用委托时要传递的实际参数。 params 不是类型,而是关键字。

【讨论】:

    【解决方案5】:

    我对 Bryan 的上述代码做了一个小的扩展,以展示如何包装多个方法调用。
    我正在使用它来将包含数据库调用的多个方法包装到一个事务中。
    谢谢布莱恩 :-)
    (你可以在LINQPad中运行以下命令进行测试)

    //Wrapper code
    public delegate void MyAction(params object[] objArgs);
    public static void RunActions(params MyAction[] actnArgs)
    {
        Console.WriteLine("WrapperBefore: Begin transaction code\n");
        actnArgs.ToList().ForEach( actn =>  actn() );
        Console.WriteLine("\nWrapperAfter: Commit transaction code");
    }
    
    //Methods being called
    public void Hash  (string s, int i, int j)  => Console.WriteLine("   Hash-method call: " + s + "###" + i.ToString() + j.ToString());
    public void Slash (int i, string s)         => Console.WriteLine("   Slash-method call: " + i.ToString()+ @"////" + s);
    
    //Actual calling code
    void Main()
    {  
      RunActions( objArgs => Hash("One", 2, 1)
                 ,objArgs => Slash(3, "four")   );
    }
    
    //Resulting output: 
    // 
    //  WrapperBefore: Begin transaction code
    //  
    //  Hash-method call: One###21
    //  Slash-method call: 3////four
    //  
    //  WrapperAfter: Commit transaction code  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多