(1)在同一个类中;
(2)方法名相同;
(3)参数列表不同。
例如下面的代码:
- public void Show()//(1)
- {
- Console.WriteLine("Nothing");
- }
- public void Show(int number)//(2)
- {
- Console.WriteLine(number);
- }
- /*
- public int Show(int number)//(3)
- {
- Console.WriteLine(number);
- return number % 5;
- }
- */
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace OverrideDemo
- {
- /// <summary>
- /// 说明:本实例用于讲述重载的关系
- /// 作者:周公
- /// 日期:2008-09-04
- /// 首发地址:http://blog.csdn.net/zhoufoxcn
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- String s = null;
- Show(s);
- Object o = "123";
- Show(o);
- }
- static void Show(string s)
- {
- Console.WriteLine("String");
- }
- static void Show(Object o)
- {
- Console.WriteLine("Object");
- }
- }
- }
以下是程序运行结果:
String
Object
(1)从String s = null;Show(s);最后调用的是static void Show(string s)这个方法我们可以得出,C#中方法调用是精确匹配的,也就是s是string类型,虽然string类型继承自object类型,尽管static void Show(Object o)也满足条件,但是方法声明中static void Show(string s)这个声明与s类型的最接近(因为s是string类型,与它最接近),所以执行static void Show(string s),而不执行static void Show(Object o)这个方法。
(2)从Object o = "123"; Show(o);最后调用的是static void Show(Object o)这个方法我们可以得出,C#中如果存在方法重载,会根据其refrence type(引用类型)来调用对象的方法,而不是根据instance type(实例类型)来调用。尽管”123”是string类型,但是它的refrence type是object类型的,所以会调用static void Show(Object o)这个方法而不是static void Show(string s)。
上面的Main()方法的IL代码如下:
{
.entrypoint
// 代码大小 24 (0x18)
.maxstack 1
.locals init ([0] string s,
[1] object o)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call void OverrideDemo.Program::Show(string)
IL_0009: nop
IL_000a: ldstr "123"
IL_000f: stloc.1
IL_0010: ldloc.1
IL_0011: call void OverrideDemo.Program::Show(object)
IL_0016: nop
IL_0017: ret
} // end of method Program::Main
- using System;
- public class Program
- { public static void Main()
- {
- Show(null);
- Show("");
- Show(1);
- }
- static void Show(Object o)
- {
- Console.WriteLine("Object");
- }
- static void Show(String s)
- {
- Console.WriteLine("String");
- }
- }
以下是程序运行结果:
String
String(感谢btbtshu、windman0925提醒此处的笔误,原来粘贴错了,成了Object了,现在已更正)
Object
(1)从Show(null)最后调用的是 static void Show(String s)方法我们更进一步可以说在C#中是方法调用尽量精确匹配的。尽管null我们可以理解为一个空object对象或者一个空字符串,但是在这里C#还是 精确为派生类。这就像我们没有钱,可以说没有一分钱也可以说没有500英镑,但是没有一分钱自然就没有500亿英镑,所以我们跟别人说没有钱的时候没有必 要说没有500亿英镑一样。在这里自然null就表示空字符串。所以Show(null)这个方法会调用static void Show(String s)这个方法。
这有点像下面的情况:
一次活动大会上,主持人说:“身高不到1.60m的请坐在1到3排,身高不到1.75m的请做到4到6排,其他的请随便坐。”
上 面的语句似乎有些逻辑方面的问题,应该说身高超过1.60m但是不到1.75m的请坐到4到6排。但是如果你面对着一群拿着枪的强盗,他说上面的话时,恰 好你也在场并且你的身高是1.55m,你会坐到哪一排?你总不可能冒着挨一枪的危险去纠正他的逻辑错误吧?最好的办法是坐到1到3排。因为无论怎么说你的 身高是绝对满足不到1.60m这个条件的(尽管你的身高也满足强盗说的第二个条件,即身高不到1.75米,但是你肯定不会冒这个危险,从上下句的意思我们 也能推断出人家的意思就是身高在1.61m到1.74m之间的人坐4到6排)。
在上面的代码中,你在运行环境的眼中就是一个持枪的强盗,虽然 null可以理解为null类型的string或者null类型的object,但是它不能向你问清楚这个到底是null类型的string或者null 类型的object,因为string是Object的派生类,所以它按照null类型的string来调用相应的方法了。
(2)从 Show("")最后调用static void Show(String s)这个方法进一步证明了方法调用是尽量选择参数最匹配的那个执行。因为Show("")相当于:string s = ""; Show(s);s的引用类型是string,所以会调用static void Show(String s)这个方法。
我们在这里可以假设一下:假如存在一个类A是String类的派生类(实际上string类是sealed的,也就是不可继承的,所以我说了是假设),并且存在在上面的代码改变如下:
- using System;
- public class Program
- { public static void Main()
- {
- Show(null);
- Show("");
- }
- static void Show(Object o)
- {
- Console.WriteLine("Object");
- }
- static void Show(String s)
- {
- Console.WriteLine("String");
- }
- static void Show(A a)//假设A是String的派生类,当然实际上String类并没有派生类,这里仅仅是假设
- {
- Console.WriteLine("A");
- }
- }
A
String
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 32 (0x20)
.maxstack 8
IL_0000: nop
IL_0001: ldnull
IL_0002: call void OverrideDemo.Program::Show(string)
IL_0007: nop
IL_0008: ldstr ""
IL_000d: call void OverrideDemo.Program::Show(string)
IL_0012: nop
IL_0013: ldc.i4.1
IL_0014: box [mscorlib]System.Int32
IL_0019: call void OverrideDemo.Program::Show(object)
IL_001e: nop
IL_001f: ret
} // end of method Program::Main
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace OverrideDemo
- {
- /// <summary>
- /// 说明:本实例用于讲述重载的关系
- /// 作者:周公
- /// 日期:2008-09-04
- /// 首发地址:http://blog.csdn.net/zhoufoxcn
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- Show(null);
- Show("");
- Show(1);
- }
- static void Show(string s)
- {
- Console.WriteLine("String");
- }
- static void Show(Object o)
- {
- Console.WriteLine("Object");
- }
- static void Show(Program p)//Program是当前方法所在的类
- {
- Console.WriteLine("Program");
- }
- }
- }
哈哈,上面的程序代码是没有运行结果的,因为它没有办法编译!编译情况如下:
为什么不能通过编译呢?
原 因就出在Show(null)这个方法这里!如果仅仅有static void Show(string s)和static void Show(Object o)方法构成重载关系,那么null我们既可以理解为空string引用也可以理解为空Object引用,因为string类型的限制更精确一些,所以 C#会按照最精确地匹配成string类型,因而会执行static void Show(string s)这个方法。这是在前面的代码中已经被证明的。可是现在多了一个static void Show(Program p)方法的重载,null既可以理解成空string类型引用,也可以理解成空Program类型引用,因为string类和Program类都是 Object类的派生类,所以按照前面的推论自然不会当成空Object类型的引用。因为String类和Program类之间不存在继承关系,按照最精 确匹配原则,编译器无法决定匹配成String类还是Program类最精确,所以编译无法通过。