C# - 如何“重载”委托?

问题描述:

首先,我正在阅读一些论坛和MSDN的帮助,并且都表示不能重载委托。C# - 如何“重载”委托?

现在,我想有这样的事情:

public delegate void OneDelegate(); 
public delegate void OneDelegate(params object[] a); 

public void DoNothing(params object[] a) {} 
public void DoSomething() { /* do something */ } 

private OneDelegate someFunction; 

someFunction = new OneDelegate(DoSomething); 
someFunction = new OneDelegate(DoNothing); 

所以,就像你知道的,你不能这样做,因为OneDelegate仅指第一个,而不是第二个。但是,有没有办法做到这一点?或类似的东西?

PS1:我不想有任何数量的OneDelegate声明,不只是一个或两个。
PS2:对不起,我的英语不好。

+2

最接近你可以使用泛型重载,就像所有的Action 和Func 重载一样。 (泛型参数表示参数类型和返回类型。)当然,一旦你走了那么远,它就会出现这样的问题:为什么不首先使用Action 和Func ? – 2010-09-19 23:57:24

+1

我想只有这个函数的一个类型,所以我可以说“嘿,这里你有一个函数,叫它!”。我不能用Action 和Func 来做到这一点。 – 2010-09-20 00:05:56

想象一下,这是可能的。假如我能有一个重载的代表:

public delegate void OneDelegate(int i); 
public delegate void OneDelegate(string s); 

现在想象一下,我宣布这种类型的变量,然后分配一个功能它,例如:

OneDelegate myDelegate = StringMethod; 

其中StringMethod正是如此宣称:

public void StringMethod(string s) { Console.WriteLine(s); } 

现在你传递myDelegate其他一些代码,该代码执行此操作:

myDelegate(47); 

你预计在这种情况下会发生什么?运行时如何使用整数参数调用StringMethod()

如果你真的想要一个委托,它可以在任何采取任何一组参数,那么唯一的选择就是有一个带有params object[]阵列:

public delegate void OneDelegate(params object[] parameters); 

但你必须分配给它实际上可以处理任何对象数组,例如一个函数:

public void MyMethod(params object[] parameters) 
{ 
    if (parameters == null || parameters.Length == 0) 
     throw new ArgumentException("No parameters specified."); 
    if (parameters.Length > 1) 
     throw new ArgumentException("Too many parameters specified."); 

    if (parameters[0] is int) 
     IntMethod((int) parameters[0]); 
    else if (parameters[0] is string) 
     StringMethod((string) parameters[0]); 
    else 
     throw new ArgumentException("Unsupported parameter type."); 
} 

正如你所看到的,这就会变得混乱真正的快。因此,我向你提出,如果你需要这样一个代表,你可能在你的建筑设计的某个地方犯了一个错误。在继续执行之前确定此缺陷并修复设计,否则代码的可维护性将受到影响。

+1

也许他的建筑设计中的“错误”是使用C#,那么? F#(以及其他具有模式匹配的函数式语言)对于不带任何内容或列表的函数没有问题。 – Gabe 2010-09-20 04:31:27

+0

@加布:够公平 - 但请记住,F#是一种完全不同的编程模式,可能适用于他的特定项目,也可能不适合。 – Timwi 2010-09-20 04:40:17

+3

我并不是建议他想使用F#。我只是不同意C#的限制可能是由于程序设计不佳而不是C#的糟糕设计(或者缺点)所导致的。 – Gabe 2010-09-20 04:58:05

Action类“这样做”。这是一个与模板的代表,这样你就可以有一个这样的委托:

public delegate void D<T>(params T[] arg); 

func() { 
    D<object> d1; 
} 

这可能是接近你会得到的,即你需要一个模板类型作为参数。

编辑:基于评论我想你是在将代表传递给另一个函数之后。你也可以通过传递参数来完成它。不幸的是,如果不使用参数fire的params参数,你不能这样做。

public void bar() { 
    D<string> d = ...; 
    fire(d, "first", "second"); 
    fire(d); // also works 
} 

public void fire<T>(D<T> f, params T[] args) { 
    f(args); 
}