无法调用基类方法
public class MyBaseClass
{
public void PrintTheValue(int inputValue)
{
Console.WriteLine(" Printed from Base class method " + inputValue);
}
}
public class MyDerivedClass : MyBaseClass
{
public void PrintTheValue(long inputValue)
{
Console.WriteLine(" Printed from Derived class method " + inputValue);
}
}
如果我尝试调用该函数,
public static void Main()
{
long longValue = 5;
int intValue = 6;
MyDerivedClass derivedObj = new MyDerivedClass();
derivedObj.PrintTheValue(longValue);
derivedObj.PrintTheValue(intValue);
Console.Read();
}
输出令我惊讶,
从派生类方法5中打印 从衍生类方法6打印
为什么我无法调用基类的功能?
我知道什么是重载和覆盖,我认为它应该调用基类方法,
我也试过了明确的演员,derivedObj.PrintTheValue((int)longValue);
但结果相同。
答案 0 :(得分:3)
我相信你被困在Overloading Methods in a base class中 .NET运行时处理它的方式非常有趣,因为它始终支持最派生的编译时类型,这意味着它总是会尝试调用最接近调用类的方法(适用于调用)。方法。
技术细节:
根据{{3}},提到
例如,方法调用的候选集不包括标记为override的方法(第7.3节),如果派生类中的任何方法适用,则基类中的方法不是候选方法(第7.5.5.1节)。
进一步阅读详细说明可以发现,.net通过Overload resolution构建了适用于method invocation的候选方法,其中在方法调用中明确提到了
所述
- 构造方法调用的候选方法集。从与先前成员查找(第7.3节)找到的与M相关联的方法集开始,该集合被简化为适用于参数列表A的那些方法。集合缩减包括应用以下规则对于集合中的每个方法TN,其中T是声明方法N的类型:
- 如果N不适用于A(第7.4.2.1节),则从集合中删除N.
- 如果N适用于A(第7.4.2.1节),那么在基本类型T中声明的所有方法都将从集合中删除。
当满足以下所有条件时,函数成员被称为关于参数列表A的适用函数成员:
A中的参数个数与函数成员声明中的参数个数相同。 对于A中的每个参数,参数的参数传递模式(即value,ref或out)与相应参数的参数传递模式相同,并且 ----对于ref或out参数,参数的类型与相应参数的类型相同。毕竟,ref或out参数是传递的参数的别名。
----对于值参数或参数数组,存在从参数类型到相应参数类型的隐式转换(第6.1节),或
上述细节可以用简单的例子来解释,
public class VMBase
{
public int Add(int a, int b)
{
Console.WriteLine("Base class method invoked");
return a + b;
}
}
public class MyVMBase : VMBase
{
public long Add(long a , long b)
{
Console.WriteLine("Derived class method invoked");
return a + b;
}
}
public static void Main()
{
MyVMBase myObj = new MyVMBase();
int imy = 5;
int j = 6;
int myaddValue = myObj.Add(imy, j); //COMPILE TIME ERROR Cannot implicitly convert type 'long' to 'int'. An explicit conversion exists (are you missing a cast?)
long myaddValue2 = myObj.Add(imy, j); // NO ERROR
}
从上面的方法可以看出,报告了编译时错误,这意味着它将始终调用派生类的方法public long Add(long a , long b)
答案 1 :(得分:1)
@Prateek:原因是派生类接受了即使对于整数值也满足的long值,因此你可以看到基类永远不会被命中。
了解代码的工作方式我已经做了一个小修改,如下所示。试试看。你会知道它进出...... :)
public class MyBaseClass
{
public void PrintTheValue(long inputValue)
{
Console.WriteLine(" Printed from Base class method " + inputValue);
}
}
public class MyDerivedClass : MyBaseClass
{
public void PrintTheValue(int inputValue)
{
Console.WriteLine(" Printed from Derived class method " + inputValue);
}
}
static void Main(string[] args)
{
long longValue = 5;
int intValue = 6;
MyDerivedClass derivedObj = new MyDerivedClass();
derivedObj.PrintTheValue(longValue);
derivedObj.PrintTheValue(intValue);
Console.Read();
}
输出就像这样..