47

null 許容型でいくつかのテストを行っていましたが、期待どおりには機能しませんでした。

int? testInt = 0;
Type nullableType = typeof(int?);
Assert.AreEqual(nullableType, testInt.GetType()); // not the same type

これも機能しません:

DateTime? test = new DateTime(434523452345);
Assert.IsTrue(test.GetType() == typeof(Nullable)); //FAIL 

DateTime? test = new DateTime(434523452345);
Assert.IsTrue(test.GetType() == typeof(Nullable<>)); //STILL FAIL

私の質問は、testInt.GetType() が int を返し、typeof(int?) が真の null 許容型を返すのはなぜですか?

4

4 に答える 4

57

MSDNによると:

Nullable 型で GetType を呼び出すと、型が暗黙的に Object に変換されるときにボックス化操作が実行されます。したがって、GetType は、Nullable 型ではなく、基になる型を表す Type オブジェクトを常に返します。

null 許容オブジェクトをボックス化すると、基になる型のみがボックス化されます。

繰り返しますが、MSDNから:

null 以外の null 許容値型をボックス化すると、値型をラップする System.Nullable ではなく、値型自体がボックス化されます。

于 2009-04-24T10:46:11.537 に答える
22

Romainの正解に加えて、「実際の」型を比較したい場合(つまり、null許容型をその基になる型に暗黙的に変換せずに)、次のような拡張メソッドを作成できます。

public static class MyExtensionMethods
{
    public static Type GetRealType<T>(this T source)
    {
        return typeof(T);
    }
}

次に、次のテストを試してください。

int? a = 0;
Console.WriteLine(a.GetRealType() == typeof(int?));         // True
Console.WriteLine(a.GetRealType() == typeof(int));          // False

int b = 0;
Console.WriteLine(b.GetRealType() == typeof(int));          // True
Console.WriteLine(b.GetRealType() == typeof(int?));         // False

DateTime? c = DateTime.Now;
Console.WriteLine(c.GetRealType() == typeof(DateTime?));    // True
Console.WriteLine(c.GetRealType() == typeof(DateTime));     // False

DateTime d = DateTime.Now;
Console.WriteLine(d.GetRealType() == typeof(DateTime));     // True
Console.WriteLine(d.GetRealType() == typeof(DateTime?));    // False

編集...

完全を期すために(そして以下のSLaksのコメントによって促されます)、これsourceは、がnullまたはNullable<>;の場合にのみコンパイル時タイプを使用する代替バージョンです。それ以外の場合GetTypeは、ランタイムタイプを使用して返します。

public static class MyExtensionMethods
{
    public static Type GetRealType<T>(this T source)
    {
        Type t = typeof(T);

        if ((source == null) || (Nullable.GetUnderlyingType(t) != null))
            return t;

        return source.GetType();
    }
}
于 2009-04-24T12:14:02.217 に答える
3

C# は、値型の格納場所が から派生した型のインスタンスを保持し、その型が から派生したものSystem.ValueTypeであると見なしますがSystem.Object、実際にはそうではありません。から派生した各型は、System.ValueType実際には 2 つの非常に異なる種類のものを表します。

  1. (プリミティブ型の場合) データを直接表すバイトのコレクション、または (非プリミティブ構造型の場合) パブリックおよびプライベートのすべてのフィールドの内容を保持しますが、型情報は保持しません。
  2. 上記に加えてオブジェクト ヘッダーを含むスタンドアロン ヒープ オブジェクトで、その型は System.ValueType から派生します。

値型の格納場所は最初のものを保持します。値型のヒープ オブジェクトは秒を保持します。

さまざまな理由から、MicrosoftNullable<T>は最初の使用のみをサポートする必要があると判断しました。タイプの格納場所をNullable<T>ヒープ オブジェクトへの参照を期待するコードに渡そうとすると、システムはその項目を true のT場合HasValueは に変換し、そうでない場合は単に null 参照を渡しHasValueます。型のヒープ オブジェクトを作成する方法はありますがNullable<T>、値型の格納場所をヒープ オブジェクトに変換する通常の方法では生成されません。

GetType()また、値の保存場所を呼び出すと、実際には保存場所の型が評価されず、代わりにその保存場所の内容がヒープ オブジェクトに変換され、結果のオブジェクトの型が返されることにも注意してください。型の格納場所は のNullable<T>オブジェクト インスタンスまたは null のいずれかに変換されるためT、オブジェクト インスタンスには、元の格納場所が であったかどうかはわかりませんNullable<T>

于 2012-04-02T20:23:34.920 に答える
0

「is」演算子を使用しているかどうかを確認する簡単な方法:

(i is Nullable<int>) || (i is Nullable<long>) || (i is Nullable<float>) || (i is Nullable<short>)

次の 2 つの MSDN ページを読んでいることがわかりました。

http://msdn.microsoft.com/en-us/library/ms366789(v=vs.90).aspx

http://msdn.microsoft.com/en-us/library/ms228597%28v=VS.90%29.aspx

乾杯!

于 2013-11-12T12:38:37.397 に答える