簡體   English   中英

為什么Nullable <>不隱藏GetType?

[英]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()返回MyBaseClassmyDerived.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.ValueTypeSystem.Object ,而Nullable<>實現任何接口。 但是,如果將我們之前的i ValueType轉換並放入編譯時類型ValueTypeobject (或dynamic )的變量中,它將失去Nullable<int>標識,並成為普通的裝箱值類型。 因此,即使將Object.GetType()virtual (這當然是非常危險的),它也什至沒有幫助。

結論:運行時類型是Nullable<>當且僅當在編譯時類型是Nullable<>所以這種“問題”不感興趣的修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM