[英]Why does Nullable<> not hide GetType?
出於這個問題, 為什么n.GetHashCode()可以工作,但是n.GetType()會拋出異常? 喬恩給出的答案使我想到了這個問題:為什么Nullable<>
隱藏GetType
:
public new Type GetType()
{
return GetValueOrDefault().GetType();
}
因為那
int? i = null;
Console.WriteLine(i.GetType().Name);
應該工作,不是嗎? 我是否缺少明顯的東西? 有哪些警告? 我嘗試了google,但沒有找到任何令人滿意的解釋。
更新 :澄清一下。 這有效:
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());
我認為這是因為GetType
返回當前實例的確切運行時類型。 在這種情況下,它沒有運行時類型,因為它引用了null
。
考慮以下示例:
MyBaseClass myBase = null;
MyDerivedClass myDerived = null;
object o = myDerived;
MyBaseClass b = myDerived;
如果myBase.GetType()
返回MyBaseClass
而myDerived.GetType()
返回MyDerivedClass
,那么o.GetType()
和b.GetType()
返回什么?
Nullable
不會簡單地隱藏object.GetType
並在其為null
時返回其編譯時類型的原因可能是因為它會破壞GetType
的合同。
我認為他們之所以沒有這樣做,是因為用一個具有相同名稱和簽名的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>
將是一項重大更改。 那是因為今天的樣子,由於Nullable<>
的神奇裝箱, i
將被裝箱為null
引用或裝箱的int
( 而不是裝箱的Nullable<int>
)。
但是:(有能力的)程序員真的沒有理由對編譯時類型 T?
的變量(或其他表達式)使用.GetType()
T?
,因為他知道實際類型與編譯時類型相同,即typeof(T?)
。 他還知道基礎類型是typeof(T)
。
出於相同的原因,對於“常規”(不可為空)的值類型T
,當編譯時類型為T
,對於程序員使用.GetType()
,因為他知道結果始終為typeof(T)
。 這是因為所有值類型都是密封類型。 同樣,對於密封的引用類型(並且沒有類型參數是.GetType()
或.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.ValueType
和System.Object
,而Nullable<>
實現任何接口。 但是,如果將我們之前的i
ValueType
轉換並放入編譯時類型ValueType
或object
(或dynamic
)的變量中,它將失去其Nullable<int>
標識,並成為普通的裝箱值類型。 因此,即使將Object.GetType()
為virtual
(這當然是非常危險的),它也什至沒有幫助。
結論:運行時類型是Nullable<>
當且僅當在編譯時類型是Nullable<>
所以這種“問題”不感興趣的修復。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.