无法调用基类方法

时间:2014-01-09 06:59:56

标签: c# override overloading

无法调用基类方法

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);但结果相同。

2 个答案:

答案 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中声明的所有方法都将从集合中删除。
    •   
  •   

正如Member lookup rules

所述
  

当满足以下所有条件时,函数成员被称为关于参数列表A的适用函数成员:
   

  • A中的参数个数与函数成员声明中的参数个数相同。    
  • 对于A中的每个参数,参数的参数传递模式(即value,ref或out)与相应参数的参数传递模式相同,并且
        ----对于值参数或参数数组,存在从参数类型到相应参数类型的隐式转换(第6.1节),或
  •    ----对于ref或out参数,参数的类型与相应参数的类型相同。毕竟,ref或out参数是传递的参数的别名。

    上述细节可以用简单的例子来解释,

    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();
        }
    

    输出就像这样..
    enter image description here