我可以在Action或Func委托中使用参数吗?

53

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

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

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

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

有什么帮助!


1
params不是一种类型,也就是说你可以在类型定义中使用ref吗? - Saeed Amiri
5个回答

50

那这个解决方法怎么样?

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

4
你用 lambda 怎么调用这个? - toddmo

12

在C#中不支持可变数量的类型参数。

这就是为什么有许多针对 Action<...>, Func<...>Tuple<...> 的声明。虽然这将是一个有趣的功能,但在 C++0x 中有实现


不确定它在泛型方面的效果如何(与模板相对)。 - CodesInChaos

7
你可以尝试这个。它允许任意数量的参数,并且如果你传递错误数量或类型的参数,你将在编译时获得错误提示。
public delegate T ParamsAction<T>(params object[] oArgs);

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

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

这是一种非常好的做法... 干得好,先生。 - Gwasshoppa
Bryan,这是一段很棒的代码。我在上面添加了一个小扩展,以展示如何包装多个方法调用。我正在使用它来将包含数据库调用的多个方法包装成单个事务。 谢谢 Bryan :-) - kamgman
1
这应该返回结果而不是 T 吗? - Mark Lauter
如果你不能执行 LogAction<Foo>("Hello world.", (p1,p2,p3) => GetFoo(p1,p2,p3));,那这有什么意义呢?减去…… - Philipp Munin

3

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


2

我对Bryan的代码进行了轻微的扩展,以展示如何包装多个方法调用。
我正在使用这个来将包含数据库调用的多个方法包装成一个事务。
谢谢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  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接