2011-04-05 82 views
4

從這個問題why does n.GetHashCode() work but n.GetType() throws and exception?即將答案喬恩送給促使我這樣一個問題:爲什麼不Nullable<>隱藏GetType爲什麼Nullable <>不隱藏GetType?

public new Type GetType() 
{ 
    return GetValueOrDefault().GetType(); 
} 

因爲那麼這

int? i = null; 
Console.WriteLine(i.GetType().Name); 

應該工作,不應該嗎?我錯過了明顯的東西嗎?什麼是警告?我試過谷歌,但沒有找到任何令人滿意的解釋。

更新:澄清:有點。這工作:

int? i = null; 
Console.WriteLine(i.GetHashCode()); 

爲什麼i.GetType()拋出的唯一原因是因爲GetType不是虛擬的,不能被重寫。所以當調用它時,i被裝箱到對象中,導致null然後拋出。但是,如果Nullable會這樣

public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return GetValueOrDefault().GetType(); 
    } 
} 

來實現,那麼這將使得行爲更加一致(恕我直言)的問候,所有這一切會工作,而不是僅僅前兩個電話:

int? i = null; 
Console.WriteLine(i.GetHashCode()); 
Console.WriteLine(i.ToString()); 
Console.WriteLine(i.GetType()); 
+2

你會如何隱藏一個繼承自Object的方法? – Kevin 2011-04-05 09:21:22

+1

此外,你爲什麼要? – 2011-04-05 09:27:42

+3

是的,的確,爲什麼'null.GetType()'拋出空引用異常:) – Poma 2011-04-05 09:55:35

回答

2

我認爲這是因爲GetType返回當前實例的精確運行時類型。在這種情況下,它沒有運行時類型,因爲它引用了null

考慮這個例子:

MyBaseClass myBase = null; 
    MyDerivedClass myDerived = null; 
    object o = myDerived; 
    MyBaseClass b = myDerived; 

如果myBase.GetType()將返回MyBaseClassmyDerived.GetType()將返回MyDerivedClass,那應該o.GetType()b.GetType()回報?

原因Nullable並不僅僅隱藏object.GetType當它是null返回其編譯時間類型,可能是因爲它會破壞GetType的合同。

+0

如上所述'int?'與'Nullable '相同,當您在'Nullable '上調用'GetType'時,它將返回'typeof(T)'。這是現有的行爲。 – ChrisWue 2011-04-05 10:27:28

+0

@ChrisWue不,它不返回typeof(T),它調用從'object'繼承的'GetType'並返回它的運行時類型。請參閱:http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx。也許你對'Type.GetType'感到困惑? – 2011-04-05 10:38:04

+0

好的,也許我表達了它不是很正確,但'GetType'返回的基礎類型在'Nullable '上調用時。 – ChrisWue 2011-04-05 20:03:05

0

我認爲他們沒有這樣做的原因是,通過new方法隱藏具有相同名稱和簽名的繼承方法通常是一個好主意。

如果他們選擇其實隱藏Object.GetType(),問題是他們是否應該返回Nullable<T>結構或基礎類型的類型。這將是兩種:

public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return typeof(Nullable<T>); 
    } 
} 

或:

public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return typeof(T); 
    } 
} 

如果您有:

int? i = null; 

或:

int? i = 42; 

i 「真正」 的運行時類型當然Nullable<int>(也稱爲int?)。當然,現在引入一個新的GetType方法(在.NET版本5.0中說)返回Nullable<int>將是一個突破性的變化。這是因爲它是今天的方式,i將盒裝到無論是null引用或盒裝int盒裝Nullable<int>),因爲Nullable<>神奇拳。

但是:實在是沒有理由編譯時類型T?的(能夠)程序員曾經使用.GetType()一個變量(或其他表達式),因爲他知道的實際類型與編譯時類型相同,即typeof(T?)。他也知道底層的類型是typeof(T)

出於同樣的原因,對於「正常」(不能爲空)值類型T,它是沒有用的程序員使用.GetType()當編譯時類型爲T,因爲他知道的結果總是是typeof(T)。這是因爲所有值類型都是密封的類型。另外,對於密封的參考類型(並且其類型參數不共同或逆變),.GetType()是無用的。

舉個例子:

string str = ...; 
... 
var t = str.GetType(); // This is really useless. If str is null 
         // an exception is thrown. Otherwise the 
         // t will ALWAYS be typeof(string) because 
         // the class System.String is a sealed class. 

Nullable<>的結構的基類是System.ValueTypeSystem.Object,和Nullable<>實現沒有接口。但是如果我們前面的i被投入並且被放入編譯時類型ValueTypeobject(或dynamic)的變量中,則其失去其身份Nullable<int>,並且變成普通的盒裝值類型。因此,即使Object.GetType()被製作爲virtual(這當然是非常危險的),它甚至不會有幫助。

結論:當且僅當編譯時類型爲Nullable<>時,運行時類型爲Nullable<>,所以這個「問題」不是有意修復的。

相關問題