当前位置:文档之家› C# 方法重载

C# 方法重载

c#方法重载2008-11-14 14:27首先我们说一下什么是方法重载。

在面对对象这样的高级语言中都允许我们在一个类中定义多个方法名相同、方法间参数个数和参数顺序不同的方法,对于参数个数不同或者参数列表不同的情况我们称之为参数列表不同。

需要注意的是这里没有提到方法的返回值。

也就是决定方法是否构成重载有两个条件:(1)在同一个类中;(2)方法名相同;(3)参数列表不同。

例如下面的代码:1. public void Show()//(1)2. {3. Console.WriteLine("Nothing");4. }5.6. public void Show(int number)//(2)7. {8. Console.WriteLine(number);9. }10. /*11. public int Show(int number)//(3)12. {13. Console.WriteLine(number);14. return number % 5;15. }16. */对于上面的代码,(1)没有参数,(2)使用了一个int类型的参数,(1)和(2)之间就构成了重载。

(2)与(3)相比仅仅返回值不同,虽然重载不关心返回值的不同,但是在C#中不允许存在方法名和参数列表相同、返回值不同的方法,所以(2)和(3)不能同时存在于代码中,(3)如果不注释掉上面的代码是没有办法通过编译的。

上面我们仅仅讨论了重载的一些基本常识,下面我们探讨一下一些情况稍微复杂的重载情况。

首先我们看第一个版本:ing System;ing System.Collections.Generic;ing System.Text;4.space OverrideDemo6.{7. /// <summary>8. /// 说明:本实例用于讲述重载的关系9. /// 作者:周公10. /// 日期:2008-09-0411. /// 首发地址:/zhoufoxcn12. /// </summary>13. class Program14. {15. static void Main(string[] args)16. {17. String s = null;18. Show(s);19. Object o = "123";20. Show(o);21. }22.23. static void Show(string s)24. {25. Console.WriteLine("String");26. }27.28. static void Show(Object o)29. {30. Console.WriteLine("Object");31. }32. }33.}大家猜猜这个程序的运行结果是什么?以下是程序运行结果:StringObject对以上代码进行分析,我们发现Show()方法有两种形式,一种是string类型的参数,一种是object类型参数,在一个类中存在方法名相同、参数列表不同(参数个数或者参数类型不同)的现象我们称之为overloading,即重载。

不过这里的Show()方法的参数比较特殊,因为string类继承于Object类,也就是Show()方法的参数存在一种继承关系。

从结果我们可以得出两点结论:(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 voidShow(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代码如下:.method private hidebysig static void Main(string[] args) cil managed{.entrypoint// 代码大小 24 (0x18).maxstack 1.locals init ([0] string s,[1] object o)IL_0000: nopIL_0001: ldnullIL_0002: stloc.0IL_0003: ldloc.0IL_0004: call void OverrideDemo.Program::Show(string)IL_0009: nopIL_000a: ldstr "123"IL_000f: stloc.1IL_0010: ldloc.1IL_0011: call void OverrideDemo.Program::Show(object)IL_0016: nopIL_0017: ret} // end of method Program::Main从上面的IL代码我们可以看出对于string s=null;这句代码在IL中表示为:ldnull。

再根据上面的结论,我们看下面的代码:ing System;2.public class Program3.{ public static void Main()4. {5. Show(null);6. Show("");7. Show(1);8. }9.10. static void Show(Object o)11. {12. Console.WriteLine("Object");13. }14.15. static void Show(String s)16. {17. Console.WriteLine("String");18. }19.20.}猜猜上面的代码执行结果会是怎样的?以下是程序运行结果:StringString(感谢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的,也就是不可继承的,所以我说了是假设),并且存在在上面的代码改变如下:ing System;2.public class Program3.{ public static void Main()4. {5. Show(null);6. Show("");7. }8.9. static void Show(Object o)10. {11. Console.WriteLine("Object");12. }13.14. static void Show(String s)15. {16. Console.WriteLine("String");17. }18.19. static void Show(A a)//假设A是String的派生类,当然实际上String类并没有派生类,这里仅仅是假设20. {21. Console.WriteLine("A");22. }23.24.}如果上面的假设成立,上面的代码运行结果应该如下:AString(3)为什么Show(1)会调用static void Show(Object o)这个方法呢?在这个类中与Show(1)最精确的方法重载应该是static void Show(int i)这种方法声明,但是方法中没有,因为int是继承自ValueType类,所以如果没有static void Show(int i)这种声明,那么其次接近的声明应该是static void Show(ValueType v)这种声明,可惜方法中依然没有,不过ValueType类继承自Object类,所以比static voidShow(ValueType v)还次一点的方法重载声明应该是static void Show(Object o),而类中也确实存在这种声明,所以会调用static void Show(Object o)这个方法。

相关主题