2015-11-26 44 views
3

我在C#以下类:虚拟和新的C#

public class BaseClass 
{ 
    public virtual void DoSomethingVirtual() 
    { 
     Console.WriteLine("Base.DoSomethingVirtual"); 
    } 

    public new void DoSomethingNonVirtual() 
    { 
     Console.WriteLine("Base.DoSomethingNonVirtual"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override void DoSomethingVirtual() 
    { 
     Console.WriteLine("Derived.DoSomethingVirtual"); 
    } 

    public new void DoSomethingNonVirtual() 
    { 
     Console.WriteLine("Derived.DoSomethingNonVirtual"); 
    } 
} 

class ConsoleInheritanceTrial 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Derived via Base Reference."); 

     BaseClass BaseRef = new DerivedClass(); 
     BaseRef.DoSomethingVirtual(); 
     BaseRef.DoSomethingNonVirtual(); 

     Console.WriteLine(); 
     Console.WriteLine("Derived via Dereived Reference."); 

     DerivedClass DerivedRef = new DerivedClass(); 
     DerivedRef.DoSomethingVirtual(); 
     DerivedRef.DoSomethingNonVirtual(); 

     Console.Read(); 
    } 
} 

运行的主要功能后,我得到这个:

Derived Via Base Reference 
Derived.DoSomethingVirtual 
Base.DoSomethingNonVirtual 

Derived Via Derived Reference 
Derived.DoSomethingVirtual 
Derived.DoSomethingNonVirtual 

为什么baseRef.DoSoemthingNonVirtual调用基函数?它是否与该函数的派生类中的“new”关键字有关? 我明白“虚拟”和“覆盖”的重要性。我的混淆是由声明造成的: BaseClass BaseRef = new DerivedClass();

+0

这里'new'的唯一影响是抑制警告。 –

回答

4

为什么BaseRef.DoSoemthingNonVirtual调用基函数?

这是你的宣言:

BaseClass BaseRef = new DerivedClass(); 

在这里,您创建DerivedClass类型的对象,并分配给一个变量,BaseClass类型的对它的引用。可以这样做,因为DerivedClass的基类型为BaseClass

然后在这里

BaseRef.DoSomethingNonVirtual 

调用方法DoSomethingNonVirtual

BaseRef是什么类型的?

它是BaseClass。所以这个类的方法被调用,而不是DerivedClass的方法。

所以这里的问题是,你已经创建了一个类型为DerivedClass的对象,并且你将该对象的引用赋值给一个BaseClass类型的变量。 所以CLR,当看到这个调用首次

BaseRef.DoSomethingNonVirtual 

必须解决的BaseRef类型,然后看对象的方法表,挑相应的IL并在最后产生相应的本地代码。 CLR如何解决这个问题?作为BaseClass类型的对象而不是DerivedClass

2

如果您在派生类中定义了virtual方法而您override它将在所有级别中覆盖该行为。基类将使用派生方法。这就是为什么覆盖的方法大多数情况下会在内部调用其基本实现的原因。

随着new您定义的方法具有相同的名字 - 没有更多...

基类不知道这个方法,所以它不会被调用。

3

为什么baseRef.DoSomethingNonVirtual调用基函数?

由于baseRef编译时类型是BaseClass,该方法调用被解析为BaseClass.DoSomethingNonVirtual()baseRef引用的对象的实际类型是DerivedClass,但编译器不知道它。

此方法不是虚拟的,所以当它在运行时被调用时,CLR将简单地调用BaseClass实现。