web-dev-qa-db-ja.com

C#のDateTimeでnullが許可されないのはなぜですか?

C#でDateTimeにnullを割り当てることが許可されないのはなぜですか?これはどのように実装されていますか?また、この機能を使用して、独自のクラスをnullにできないようにすることはできますか?

例:

string stringTest = null; // Okay
DateTime dateTimeTest = null; // Compile error

DateTime? C#2.0では、dateTimeTestにnullを割り当てることができ、文字列で Jon SkeetのNonNullableクラス を使用して、stringTestの割り当てでランタイムエラーを取得できます。 2つのタイプの動作が異なるのはなぜですか。

38
Jan Aagaard

DateTimeは値タイプ(struct)であり、文字列は参照タイプ(classなど)です。それが大きな違いです。参照は常にnullにすることができます。値は使用できません(ただし、Nullable<T>-つまりDateTime?)、ただしゼロ化できます(DateTime.MinValue)、これはしばしばnullと同じものとして解釈されます(特に1.1)。

87
Marc Gravell

DateTimeは構造体であり、クラスではありません。 「定義に移動」するか、オブジェクトブラウザで確認してください。

HTH!

9
Simon

ValueTypeと参照型の重要な違いは、値型にこれらの「値のセマンティクス」があることです。 DateTime、Int32、および他のすべての値タイプにはIDがありません。Int32 "42"は、同じ値を持つ他のInt32と本質的に区別できません。

すべての値タイプ「オブジェクト」は、スタック上または参照タイプオブジェクトの一部として存在します。特別なケースの1つは、値型インスタンスをオブジェクトまたはインターフェイスにキャストする場合です。これは「ボックス化」と呼ばれ、抽出できる値(「ボックス化解除」)のみを含むダミーの参照型オブジェクトを作成するだけです。 。

一方、参照タイプにはIDがあります。 「new Object()」は、他の「new Object()」と同等ではありません。これらは、GCヒープ上の個別のインスタンスだからです。一部の参照型は、Equalsメソッドとオーバーロードされた演算子を提供して、より値のように動作します。文字列「abc」は、実際には2つの異なるオブジェクトであっても、他の「abc」文字列と同じです。

したがって、参照がある場合は、有効なオブジェクトのアドレスを含めるか、nullにすることができます。値型オブジェクトがすべてゼロの場合、それらは単にゼロになります。例えば。整数ゼロ、浮動小数点ゼロ、ブールfalse、またはDateTime.MinValue。 「ゼロ」と「欠損値/ null」を区別する必要がある場合は、個別のブールフラグを使用するか、.NET 2.0のNullable <T>クラスを使用する必要があります。これは単に値にブールフラグを加えたものです。 CLRにもサポートがあり、HasValue = falseでNullableをボックス化すると、null参照になります。この構造を自分で実装した場合のように、false + zeroでボックス化された構造ではありません。

7
user83286

DateTimeは、intと同じ値型です。 nullにできるのは、参照型(文字列やMyCustomObjectなど)だけです。参照型は、ヒープ上のオブジェクトの場所への「参照」を実際に格納します。

ここに 記事があります 私はそれをよりよく説明しています。そして、ここに MSDNの記事があります

1
danswain

値型がnullになるには、他の正当な意味を持たない値が保持できる必要があります。 システムが何らかの方法で知っているものは「null」と見なされるべきです。一部の値タイプは、追加のストレージを必要とせずに最初の基準を満たすことができます。 .netがnull許容値の概念を念頭に置いてゼロから設計されていた場合、Object include a virtualIsLogicalNullproperty, and a non-virtual無効ですwhich would returntrue ifthisis null and, otherwise invoke itsIsLogicalNullproperty and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior andstructconstraint ofヌル可能(an emptyヌル可能could be boxed as an emptyヌル可能, and still be recognized asnull`)。

.net framework 2.0でnull許容値の型のサポートを提供することが決定されたとき、ただし、GuidDateTimeなどのデフォルト値を想定した多くのコードが記述されていましたnullとは見なされません。 null許容型の値の多くは、予測可能なデフォルト値(つまりnull)にあるため、null値を持っているが、他の値にデフォルト設定されている型があると、値よりも混乱が生じます。 。

1
supercat

文字列はクラスですが、DateTimeは構造です。それがnullに設定できない理由です

0
Rob Haupt