方法、实例构造函数、索引和操作符都是根据它们的签名(signature)来识别的:
一个方法的签名从左至右,由方法的名字、类型参数的数目,以及每个形式参数的类型和种类(传值、传引用,或是输出参数)组成。因此,方法在形式参数的类型里出现的任何类型参数都不是根据它的名字来识别,而是根据在方法的类型参数列表中的序号位置来识别的。方法的签名不包含:返回类型,最右边参数的params修饰符,可选的类型形参限制。
实例构造函数的签名从左至右由每一个形式参数的类型和种类(传值、传引用,或是输出参数)组成。实例构造函数的签名不包含可以为最右边参数指定的params修饰符。
索引的签名从左至右由每一个形式参数的类型组成。索引的签名既不包含元素类型,也不包含可以为最右边参数指定的params修饰符。
操作符的签名从左至右由操作符的名字,以及它的形式参数的类型组成。操作符的签名不包含返回类型。
签名的存在让对类、结构和接口成员的重载(overload)成为可能:
重载方法让类、结构或接口可以声明多个同名方法,只要它们在类、结构或接口中的签名是唯一的即可。
重载实例构造函数让类或结构可以声明多个实例构造函数,只要它们在类或结构中的签名是唯一的即可。
重载索引让类、结构或接口可以声明多个索引,只要它们在类、结构或接口中的签名是唯一的即可。
重载操作符让类或结构可以声明多个同名操作符,只要它们在类或结构中的签名是唯一的即可。
虽然out和ref参数修饰符被认为是签名的一部分,但是在一个类型中声明的成员不可以在签名里仅仅依据ref和out来区分。如果在同一个类型中声明的两个成员方法里除了将参数里的out修饰符替换成ref修饰符之外其他都一样,就会发生编译期错误。对于其他的签名匹配(例如,隐藏或覆写),ref和out都被认为是签名的一部分而不会相互匹配。这个限制的意图是:让C#可以轻易地被翻译运行在公共语言架构[CLI]之上,CLI并没有提供仅靠ref和out区别定义方法的方式。
下面的例子展示了一组重载方法声明及其签名。
- interface ITest
- {
- void F(); // F()
- void F(int x); // F(int)
- void F(ref int x); // F(ref int)
- void F(out int x); // F(out int) error
- void F(int x, int y); // F(int, int)
- int F(string s); // F(string)
- int F(int x); // F(int) error
- void F(string[] a); // F(string[])
- void F(params string[] a); // F(string[]) error
- }
interface ITest
{
void F(); // F()
void F(int x); // F(int)
void F(ref int x); // F(ref int)
void F(out int x); // F(out int) error
void F(int x, int y); // F(int, int)
int F(string s); // F(string)
int F(int x); // F(int) error
void F(string[] a); // F(string[])
void F(params string[] a); // F(string[]) error
}
注意任何ref和out参数修饰符都是签名的一部分。因此F(int)和F(ref int)是不同的签名。但是F(ref int)和F(out int)却不能在同一个接口里声明,因为它们的签名仅仅依靠ref和out来区分。同样,返回类型和params修饰符也不属于签名的一部分,所以不可以基于返回类型或是否包含params修饰符来重载声明。因此上述声明的方法F(int)和F(params string[])会导致编译期错误。
转载自:http://book.51cto.com/art/200911/160236.htm
简言之:.net能实现重载的方法要满足:方法名相同,签名不同。签名包括:参数类型、个数、顺序,ref与out不能同时出现,返回值及params修饰符不是签名的一部分
另外:委托是一种定义方法签名的类型,与委托的签名(由返回类型和参数组成)匹配的任何可访问类或结构中的任何方法都可以分配给该委托。 与重载里的方法签名不一样