2010-10-02 70 views
2

無法解釋接下來的程序發生了什麼。 GetType返回我想要返回的類型,而不是原來的類型。這是否意味着我們不能依賴GetType?是運營商是正確的。任何人都可以詳細解釋一下嗎?GetType返回不同​​於運營商使用的信息

using System; 

namespace ConsoleApplication2 
{ 
    public class MyClass 
    { 
     public Type GetType() 
     { 
      return typeof(Program); 
     } 

    } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyClass mc = new MyClass(); 

     if (mc.GetType() == typeof(Program)) 
     { 
      Console.WriteLine("Confused."); 
     } 
     if(mc is Program) 
     { 
      Console.WriteLine(mc.GetType()); // Don't get inside the if. Why? 
     } 

    } 
} 
} 

更新:我通過C#第三版閱讀的書CLR。在當它解釋了System.Object的不同方法第4章(第2頁),它說

「GetType方法是非虛, ,其防止一個類重寫此 方法和躺在它的類型」

雖然我對第一條語句表示同意,但我對MyClass類型說謊。不是我嗎?

+0

你能否證實,這裏的困惑是,mc.GetType()== typeof運算(計劃)實際評估爲真? – 2010-10-02 05:39:17

+0

是的。實際上它似乎是運算符使用一些不同的機制來檢查類型比GetType()。如果是,機制是什麼?另外上面的程序顯示我們不能相信GetType返回正確的類型。 – Tanmoy 2010-10-02 05:41:43

+2

我認爲你對創建**新**方法(隱藏祖先方法)和**覆蓋**祖先方法之間的區別感到困惑。埃裏克Lippert最近有[博客文章](http://blogs.msdn.com/b/ericlippert/archive/2010/03/29/putting-a-base-in-the-middle.aspx)觸及此(可能還有其他人,但這是我能找到的第一個)。閱讀它可以幫助你瞭解這裏發生了什麼。 – 2010-10-02 08:00:00

回答

4

is operator implemented in terms of as operator最後使用isinst IL指令。當然,這條指令並不知道你在繼承層次結構中的某些類中定義的非虛擬GetType方法。

要理解這種「混亂」的行爲讓「落實」自己的「是運營商」的版本:

public class MyClass 
{ 
    public Type GetType() 
    { 
     return typeof(Program); 
    } 

} 

class Program { 

    //this is oversimplified implementation, 
    //but I want to show the main differences 
    public static bool IsInstOf(object o, Type t) 
    { 
     //calling GetType on System.Object 
     return o.GetType().IsAssignableFrom(t); 
    } 

    static void Main(string[] args) 
    { 
     MyClass mc = new MyClass(); 

     //calling MyClass non-virtual version for GetType method 
     if (mc.GetType() == typeof(Program)) 
     { 
      //Yep, this condition is true 
      Console.WriteLine("Not surprised!"); 
     } 

     //Calling System.Object non-virtual version for GetType method 
     if (IsInstOf(mc, typeof(Program))) 
     { 
      //Nope, this condition isn't met! 
      //because mc.GetType() != ((object)mc).GetType()! 
     } 

     Console.ReadLine(); 
    }    
} 
0

它只會是真實的,如果:

if (mc is MyClass) { ... } 
1

檢查的實際運行時類型的變量。編譯器不關心你已經定義了一個名爲GetType()的方法,該方法返回另一個Type。它仍然知道變量的實際類型是MyClass

你究竟想在這裏完成什麼?爲什麼你需要你的MyClass課程模仿Program課程?

3

Object.GetType不是虛擬方法。所以mc is MyClass和有效呼籲Object.GetType而不是你的方法。

+0

它(運營商)是如何做到的?它是否首先強制mc先對象,然後調用GetType方法?另請參閱我的問題的更新。是否我們可以依賴'是',而我們不能直接使用GetType。 – Tanmoy 2010-10-02 05:53:32

+3

我相信'is'運算符歸結爲CLR中的'isinst'指令。我不知道這是如何實現的,但它可能會查詢類似於GetType的對象表。結果與使用'((object)mc).GetType()'測試相同。 – ars 2010-10-02 06:39:46

4

請注意警告,因爲它們確實存在的原因。您的代碼以下警告編譯:

Warning 1 'ConsoleApplication2.MyClass.GetType()' hides inherited member 'object.GetType()'. Use the new keyword if hiding was intended.

這意味着GetType()非虛,你正在寫的GetType()新無關方法CLR將永遠不會調用它。

+0

如果我的問題沒有說清楚,我很抱歉。它關於學術/理論上的興趣,而不是用最佳實踐來編寫產品代碼。 – Tanmoy 2010-10-02 08:01:07