2010-02-22 21 views
3

我有一些困惑與新的關鍵字,東西很好地工作,當我使用虛擬和覆蓋,但隨着新的(我想我失去了一些東西)怎樣新的關鍵字工作在派生類

class A 
{ 
    public virtual void Test() 
    { 
     Console.WriteLine("I am in A"); 
    } 
} 

class B:A 
{ 
    public override void Test() 
    { 
     Console.WriteLine("I am in B"); 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     B b = new B(); 
     b.Test(); //I am in B 
     A a = new B(); 
     Console.WriteLine(a.GetType()); // Type-B 
     a.Test(); //I am in B 
     Console.ReadKey(); 
    } 
} 
有點不同

}

現在提供新

class A 
{ 
    public void Test() 
    { 
     Console.WriteLine("I am in A"); 
    } 
} 

class B:A 
{ 
    public new void Test() 
    { 
     Console.WriteLine("I am in B"); 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     B b = new B(); 
     b.Test(); //I am in B 
     A a = new B(); 
     Console.WriteLine(a.GetType()); //B 
     a.Test(); // I am in A ? why? 
     Console.ReadKey(); 
    } 
} 

按照MSDN當使用新的關鍵字,新的類成員被調用,而不是已被替換的基類成員。這些基類成員稱爲隱藏成員,也對GetType()是類型B. 那麼,我錯了,看來它是一個愚蠢的錯誤:-)

回答

2

當您使用關鍵字new隱藏基類方法時,調用由編譯器解析,而不是在運行時解析。

因此,當您編寫a.Test時,編譯器會發出對A類的Test方法的調用。儘管a變量碰巧指B實例,編譯器並不在意,它仍然調用A上的版本。

當你調用一個虛擬方法時,編譯器會發出一個callvirt指令,告訴運行時根據實例的實際類型找到正確的調用方法。運行時知道該實例實際上是B類型的實例,並且將看到B將覆蓋該方法並調用被覆蓋的版本。

+1

這意味着這是編譯時間與運行時間..我明白了你的觀點,thnx。 – Wondering

2

退房Jon Skeet's descriptionew關鍵字的使用正。因爲a被轉換爲A,所以你正在調用A的方法,這個方法不能被覆蓋。 B碰巧有一個同名的方法。

+0

thnx for d鏈接 – Wondering

0

基本上,一旦你創建它無論從AB派生其他類,你會發現,調用base.Test()將調用A的版本,這些類的其中override而非new和那些從B派生將有B「 s版本被稱爲但不是A's。

相關問題