class OverloadAndOverride
    {
        public static void Main()
        {
            int a = 5;
            Child child = new Child();
            child.Call(a);
            Console.ReadKey();
        }     
    }    public class Base
    {
        public virtual void Call(int input)
        {
            Console.WriteLine("This is Base[int]::Call(input={0})",input);
        }
    }    public class Child : Base
    {
        public override void Call(int input)
        {
            Console.WriteLine("This is Child[int]::Call(input={0})", input);
        }        public void Call(double input)
        {
            Console.WriteLine("This is Child[double]::Call(input={0})", input);
        }
    }这段代码的输出是:
This is Child[double]::Call(input=5)Main中的Call方法IL如下IL_000c:  callvirt   instance void Demo1.Child::Call(float64)如果和您的答案一样的话,那么请告诉我,为什么?Child 中的两个Call是否是函数重载关系,如果是,为什么没有调用相匹配的方法?当然,如果把这里的Override该成new,答案显而易见。
我个人觉得对静态多态(Overload)及动态多态(Override)理解的还是比较清楚的,早绑定晚绑定也很清晰,但是遇到这个问题我看不懂了。如果高手们有兴趣,也可以就此说说多态及其应用,请不吝赐教!!!

解决方案 »

  1.   

    看来晚上大家都睡觉了,明天再来看答案,呵呵~~~
    希望得到个准确而清晰的解答~z~z~~Z~~~Z~~~~
      

  2.   

    重写和方法选择
    当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两种同名的方法,并且其参数与传递的参数兼容),则 C# 编译器将选择最佳方法进行调用。下面的方法将是兼容的:C#  复制代码 
    public class Derived : Base
    {
        public override void DoWork(int param) { }
        public void DoWork(double param) { }
    } 在 Derived 的一个实例中调用 DoWork 时,C# 编译器将首先尝试使该调用与最初在 Derived 上声明的 DoWork 版本兼容。重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配。例如:C#  复制代码 
    int val = 5;
    Derived d = new Derived();
    d.DoWork(val);  // Calls DoWork(double). 由于变量 val 可以隐式转换为 double 类型,因此 C# 编译器将调用 DoWork(double),而不是 DoWork(int)。有两种方法可以避免此情况。首先,避免将新方法声明为与虚方法同名。其次,可以通过将 Derived 的实例强制转换为 Base 来使 C# 编译器搜索基类方法列表,从而使其调用虚方法。由于是虚方法,因此将调用 Derived 上的 DoWork(int) 的实现。例如:C#  复制代码 
    ((Base)d).DoWork(val);  // Calls DoWork(int) on Derived. 
      

  3.   

    重写和方法选择
    ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_csref/html/88247d07-bd0d-49e9-a619-45ccbbfdf0c5.htm这种机制,在C#中又称为“决断”
    简单说是以“精确优先”的原则
    [1]“本类”优先于“基类”;
    [2]“精确”优先于“模糊”。从别一个侧面反映出,
    重载的情况下,
    对象调用函数是从基类发起的,
    而不是从本类发起的.现在来总结一下,C#的重载是怎么工作的,主要分两大步. 
    注:从变量的类型开始出发,暂称为"操作类型",对象本身的类型称为"源类型" 
    [1]向下(基类)方向,找到第一个实现 
    "操作类型"本身己实现该方法,可重写转向上 
    "操作类型"向下找到第一个实现该方法的基类,如果该基类可被重写,转向上,否则就是该类型 
    "操作类型"向下找到不到实现该方法的基类,转异常 
    [2]向上(扩展)方向,直到发现隐藏 
    判断当前类型是否被重写,不可被重写,则为该类型 
    如果当前类型可被重写,向上查询,直到发现new|virtaul|new virtaul|"源类型",为该类型
      

  4.   


    重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配. 
    hdt一句话点醒梦中人那~~~
      

  5.   


    To: pcnetman888 能告诉我是什么特定的情况吗?
      

  6.   

    先给你看一个简单点的情况,
    构造上的案例还要再研究一下,
    案例比较难构造,也不太好描述.最好的方法,就是上代码:#define INT
    #define DOUBLEusing System;
    using System.Reflection;public class B
    {
        public B()
        {
            Console.WriteLine("调用基类开始:ClassB!");
            int val = 100;
            this.Func(val);
        }#if INT 
        public virtual void Func(int val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassB-Func!-int");
        }
    #endif    public virtual void Func(long val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassB-Func!-long");
        }}public class BB : B
    {
        public BB()
        {
            Console.WriteLine("调用扩展类开始:ClassBB!");
            int val = 100;
            this.Func(val);
        }#if INTs
        public override void Func(int val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBB-Func!-int");
        }
    #endif    public override void Func(long val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBB-Func!-long");
        }#if DOUBLE
        public virtual void Func(double val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBB-Func!-double");
        }
    #endif
    }public class BBB : BB
    {
        public BBB()
        {
            Console.WriteLine("调用扩展类开始:ClassBBB!");
            int val = 100;
            this.Func(val);
        }#if INTs
        public override void Func(int val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBBB-Func!-int");
        }
    #endif    public override void Func(long val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBBB-Func!-long");
        }#if DOUBLE
        public override void Func(double val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBBB-Func!-double");
        }
    #endif    public void Func(string val)
        {
            Console.WriteLine("Type is {0},{1}", this.GetType(), "ClassBBB-Func!-string");
        }
    }class Test
    {
        static void Main()
        {
            BB bb = new BBB();
            int val = 100;        Console.WriteLine("变量BB类型开始:ClassBB!");
            bb.Func(val);        //Reflection
            Type[] types=new Type[3];
            types[0] = Type.GetType("B");
            types[1] = Type.GetType("BB");
            types[2] = Type.GetType("BBB");
            for( int i = 0 ; i<3;i++)
            {
                Console.WriteLine("======={0}=====",types[i].ToString());
                MemberInfo[] memberInfos = types[i].GetMembers();
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    Console.WriteLine("{0} is a {1},Name is {2}", memberInfo, memberInfo.MemberType, memberInfo.MetadataToken);
                }
            }
            Console.ReadKey();
        }
    }//[0]重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。//[1]非构造调用:派生类的原始方法相匹配的方法
    //[2]非构造调用:派生类的原始方法相兼容的方法
    //[3]非构造调用:基类的方法相匹配的方法
    //[4]非构造调用:基类的方法相兼容的方法//[5]构造调用:派生类的原始方法相匹配的方法
    //[6]构造调用:派生类的原始方法相兼容的方法
    //[7]构造调用:基类的方法相匹配的方法
    //[8]构造调用:基类的方法相兼容的方法//=======B=====
    //Void Func(Int32) is a Method,Name is 12426544*A(B)
    //Void Func(Int64) is a Method,Name is 12426552*(B)
    //=======BB=====
    //Void Func(Int64) is a Method,Name is 12426664+(B)
    //Void Func(Double) is a Method,Name is 12426672*(BB)
    //Void Func(Int32) is a Method,Name is 12426544A(B)
    //=======BBB=====
    //Void Func(Int64) is a Method,Name is 12426784+(B)
    //Void Func(Double) is a Method,Name is 12426792+(BB)
    //Void Func(Int32) is a Method,Name is 12426544A(B)
    //=======B=====
    //Void Func(Int32) is a Method,Name is 100663298A*
    //Void Func(Int64) is a Method,Name is 100663299B*
    //=======BB=====
    //Void Func(Int64) is a Method,Name is 100663301B+
    //Void Func(Double) is a Method,Name is 100663302C*
    //Void Func(Int32) is a Method,Name is 100663298A
    //=======BBB=====
    //Void Func(Int64) is a Method,Name is 100663304B+
    //Void Func(Double) is a Method,Name is 100663305C+
    //Void Func(System.String) is a Method,Name is 100663306D*
    //Void Func(Int32) is a Method,Name is 100663298A
    案例说明:
    主要是观察BBB的构造函数中的调用~~
    fun(int32)在B中定义,BBB通过"自然继承"得到
    fun(int64)在B中定义,BBB通过"重写"得到
    fun(double)在BB中定义,BBB通过"重写"得到
    最后通过比较,double在BB中原生,最接近BBB,
    最后的结果是选择fun(double)得出的结论:
    [1]如果是多层次的继承,不单是比较本类和基类,还要看哪个更接近.
    [2]同样需要考虑自然继承的情况其它:
    通过修改DEBUG,来调整其它的组合,
    可以进一步验证我的最后结果,
    在下面的贴子中发表.
    新规则总结在这个贴子的:
    http://topic.csdn.net/u/20090805/13/254df2c5-2356-438a-a7f5-7f9ce5a9b3b0.html?seed=683743527&r=59086770#r_59086770
    34楼:对"方法选择"的一个归纳