6

私が書くとき

Nullable<Nullable<DateTime>> test = null;

コンパイルエラーが発生します:

The type 'System.Datetime?' must be a non-nullable value type in order to use it as a paramreter 'T' in the generic type or method 'System.Nullable<T>'

しかしNullable<T>structそうなので、null許容ではないはずです。

だから私はこれを作成しようとしましたstruct

public struct Foo<T> where T : struct
{
    private T value;

    public Foo(T value)
    {
        this.value = value;
    }

    public static explicit operator Foo<T>(T? value)
    {
        return new Foo<T>(value.Value);
    }

    public static implicit operator T?(Foo<T> value)
    {
        return new Nullable<T>(value.value);
    }
}

今私が書くとき

        Nullable<Foo<DateTime>> test1 = null;
        Foo<Nullable<DateTime>> test2 = null;
        Foo<DateTime> test3 = null;

最初の行は問題ありませんが、2行目と3行目では、次の2つのコンパイルエラーが発生します。

The type 'System.DateTime?' must be a non-nullable value type in order to use it as a parameter 'T' in the generic type or method 'MyProject.Foo<T>'(2行目のみ)

Cannot convert null to 'MyProject.Foo<System.DateTime?> because it is a non-nullable value type'

        Foo<Nullable<DateTime>> test = new Foo<DateTime?>();

Nullable<DateTime>の場合、どちらのイベントも機能しませんstruct

概念的には、なぜnull許容であるのかを理解できます。それは、私がまだ持つことができるNullable<T>ようなものを持つことを避けます...DateTime??????????List<List<List<List<List<DateTime>>>>>

では、なぜこの制限があり、なぜこの動作を再現できないのFoo<T>でしょうか。この制限はコンパイラによって強制されますか、Nullable<T>それともコードに固有ですか?

私はこの質問を読みましたが、それは不可能であると言っているだけで、基本的にそれが不可能である理由を述べている答えはありません。

4

3 に答える 3

10

ただし、Nullableは構造体であるため、Nullableではないはずです。

Nullable<T>は確かに構造体ですが、ドキュメントstructに記載されている一般的な制約の正確な意味は次のとおりです。

type引数は値型でなければなりません。を除くすべての値タイプをNullable指定できます。詳細については、 Nullable型の使用(C#プログラミングガイド)を参照してください。

同じ理由で、あなたのライン

Foo<Nullable<DateTime>> test2 = null;

structジェネリック制約はジェネリックT引数をある意味で制限するためNullable<DateTime>、実際の引数として指定してはならないため、表示されているコンパイラエラーが発生します。

この理由は、次のような電話をかけることだった可能性があります。

Nullable<Nullable<DateTime>> test = null;

あいまいさが少ない:それは、に設定することを意味しますか、それとも実際にに設定test.HasValueすることを意味しますか?null許容型の引数に制限が与えられているため、この混乱は発生しません。falsetest.HasValuetruetest.Value.HasValuefalse

最後に、このSO質問このSO質問に対する選択された回答とコメントによって示されるように、この型はコンパイラの魔法によってサポートされているため、null割り当ては機能します。Nullable<T>Nullable<T>

于 2012-09-18T12:05:11.260 に答える
1

エラーは、Nullableのtype-parameterがnullableであってはならないことを示しています。

あなたがしていることは、許可されていないnull許容型パラメータを持つNullable型を作成することです:

Nullable<Nullable<DateTime>>

と同じです

Nullable<DateTime?>

これはまったく無意味です。すでにnull許容型の型にnull許容型が必要なのはなぜですか?

Nullableは、.NET 2.0で導入されたタイプであり、「nullable値タイプ」を使用できます。たとえば、オプションのdatetime-parameterを持つメソッドがある場合。DateTime.MinValueのような「魔法の値」を渡す代わりに、そのパラメーターを使用したくない場合は、そのメソッドにnullを渡すことができるようになりました。

于 2012-09-18T12:04:58.763 に答える
1

ジェネリッククラスwhere T: structでは、型Tをnullにすることはできません。ただし、Nullable型は、構造体にnull可能性を追加するように設計されています。技術的には構造体ですが、null値が含まれている可能性があるように動作します。このあいまいさのため、制約ではnullableの使用は許可されていません。タイプパラメータの制約をwhere T: struct参照してください。

null許容型は、特別なC#コンパイラをサポートする単なる汎用構造体ではありません。null許容型はCLR自体によってサポートされ(Jeffrey RichterによるC#経由のCLRを参照)、この特別なCLRサポートにより非再帰的になるように見えます。

  • CLRは、特別なボクシング/アンボクシングルールをサポートしており、値ではなく値を変数int? i = 1; object o = iに入れます。複数のnullableの場合-含むか値を指定する必要がありますか?intoNullable<int>o = (int??)1;intint?
  • CLRは、GetTypeとインターフェイスメンバーの呼び出しを特別にサポートしています。基になる型のメソッドを呼び出します。これは実際には、Nullable.GetType()がNullValueFlagを持っている場合に、NullObjectReference例外をスローする状況につながります。

C#に関しては、null許容型用にハードコーディングされたC#の機能がたくさんあります。この記事「NullableTypes(C#プログラミングガイド)」に基づいて、nullable型を導入する主な目的は、nullをサポートしない型にnullサポートを追加することです。論理的には、DateTime以降?すでにnullをサポートしているので、「もっと」null許容にすることはできません。

この文書はまた、次のように明確に述べています

ネストされたnull許容型は許可されていません。次の行はコンパイルされません。Nullable<Nullable<int>> n;

null許容型の特別なC#機能:

  • C#には特別な?? オペレーター。価値(int???)null ?? (int)1に解決する(int??)1必要がありますか?(int)1
  • Nullablesには特別なSystem.Nullable.GetValueOrDefaultプロパティがあります。ネストされたnullableに対して何を返す必要がありますか?
  • ? == nullと演算子のための特別な処理? != null。に値がNullable<Nullable<T>>含まれているNullable<T>が、この値がnullの場合、HasValueプロパティは何を返す必要がありますか?nullとの比較の結果はどうなりますか?
  • 特別な暗黙の変換。int?? i = 10暗黙的に変換可能である必要がありますか?
  • 明示的な変換。int i = (int??)10;サポートする必要がありますか?
  • boolの特別なサポート?typenull許容型を使用します。例(bool?)null | (bool?)true == true

では、CLRは再帰的なGetType()呼び出しをサポートする必要がありますか?値をボクシングするときにNullableラッパーを削除する必要がありますか?1つのレベルの値に対応する必要がある場合は、他のすべてのレベルにも対応しないのはなぜですか。考慮すべきオプションが多すぎ、再帰処理が多すぎます。

最も簡単な解決策は、Nullable<Nullable<T>>コンパイルできないようにすることです。

于 2012-09-18T13:50:59.800 に答える