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)理解的还是比较清楚的,早绑定晚绑定也很清晰,但是遇到这个问题我看不懂了。如果高手们有兴趣,也可以就此说说多态及其应用,请不吝赐教!!!
{
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)理解的还是比较清楚的,早绑定晚绑定也很清晰,但是遇到这个问题我看不懂了。如果高手们有兴趣,也可以就此说说多态及其应用,请不吝赐教!!!
希望得到个准确而清晰的解答~z~z~~Z~~~Z~~~~
当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两种同名的方法,并且其参数与传递的参数兼容),则 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.
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|"源类型",为该类型
重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配.
hdt一句话点醒梦中人那~~~
To: pcnetman888 能告诉我是什么特定的情况吗?
构造上的案例还要再研究一下,
案例比较难构造,也不太好描述.最好的方法,就是上代码:#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楼:对"方法选择"的一个归纳