selectedItem
には2つのフィールドがあります。
int? _cost
_string _serialNumber
_この例では、selectedItem
の__cost
_および__serialNumber
_は両方ともnullです。私はそれらのプロパティを介してselectedItem
のフィールドを読み、テキストボックスにそれらの値を入力しています...
_TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
_
私はSerialNumber.ToString()
が冗長であることを理解していますが(既に文字列であるため)、これがこの例外の原因となっている理由がわかりません。
Null可能オブジェクトには値が必要です。
int? _cost
_はnull可能で、値がありませんが、例外は発生しません。string _serialNumber
_はnull可能で、値がありませんが、does例外が発生します。これは question に触れており、基本的に同じことを求めていますが、指定された回答はありません。また、null可能int
の理由も説明されていません。たとえば、nullable intでは.ToString()
を使用できますが、null文字列では使用できませんか?
string
タイプのnull
は実際には何も指していないため、メモリ内にオブジェクトはありません。
だが int?
type(nullable)は、値がnull
に設定されていても、一部のオブジェクトを指します。
Jeffrey Richterの「C#を介したCLR」を読むと、DB nullでの作業をより便利にするために、null許容型は、いくつかのカプセル化されたロジックを持つ一般的な型のファサードクラスにすぎないことがわかります。
Null許容型については、 msdn を確認してください。
Nullable<int>
はstruct
であり、実際にnullにすることはできません。したがって、「null」構造体のメソッド呼び出しは引き続き機能します。
_cost == null
を有効な式にする「コンパイラマジック」があります。
int?
は実際にはそれ自体がオブジェクトではありませんが、Nullable<int>
オブジェクトです。
したがって、int? _Cost
を宣言すると、実際にはNullable<int> _Cost
が宣言され、_Cost.Value
のプロパティはundefined
であり、_Cost
オブジェクト自体ではありません。
int
、bool
、decimal
などのnon nullable
型を簡単に使用することは、実際には構文上の砂糖です。
[〜#〜] msdn [〜#〜] によると:
構文
T?
はSystem.Nullable<T>
の省略形であり、T
は値の型です。 2つの形式は交換可能です。
文字列は参照型ですが、null許容intは値型です。ここに違いの良い議論があります http://www.albahari.com/valuevsreftypes.aspx 。
Nullableは実際には、HasValueとValueの2つのプロパティを公開する構造体です。これを行うと、エラーが発生します。
int? i = null;
i.Value.ToString()
あなたのintかどうかを確認するには?アクセスできる値があるi.HasValue
理由は簡単です。 _int?
_または _Nullable<int>
_ はstructまたは 値のタイプ 、nullにすることはできません。
だから私たちが行うとどうなりますか:
_int? _cost = null;
_
__cost
_には、Value
とHasValue
の2つのフィールドがあります。null
を__cost
_に割り当てると、そのHasValue
フラグが次のように設定されます。 false
およびValue
フィールドには、_int?
_の場合はdefault(T)
が割り当てられ、_0
_になります。
__cost
_でToString
を呼び出すと、_Nullable<T>
_はToString
のオーバーライド定義を持ちます。これは、 Microsoftが提供するソース参照 を見ると次のように実装されています:
_public override string ToString() {
return HasValue ? value.ToString() : "";
}
_
したがって、__cost
_にはnull
が割り当てられているため、空の文字列が返されます。
さて、_string _serialNumber
_の場合です。 string
であるため、これは参照型であり、null
を純粋に保持できます。 null
を保持している場合、ToString
を呼び出すと、期待どおりにnull参照例外が生成されます。
次のように表示されます: 値のタイプと参照タイプ-MSDN
その理由は、コンパイラがプリミティブデータ型を検出すると、対応するオブジェクトにラップすることです。 toString()メソッドの呼び出しは、ここでは間接的な呼び出し(ラップしてからメソッドを呼び出す)であり、例外はそこで処理されます。文字列の場合は、メソッドを直接呼び出します。 nullを指す場合、メソッドは例外をスローします。
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
System.Stringのメンバーである関数 ToString() を呼び出しているため、エラーが発生します。この関数は、System.Stringのこのインスタンスを返します。実際の変換は行われません。また、Stringは参照型です。参照型には、データを保持する別のメモリ位置へのポインタが含まれています。
TextBox1.Text = selectedItem.Cost.ToString(); //no error
System.Integerのメンバーである関数 ToString() を呼び出しているため、エラーは発生しません。この関数は、このインスタンスの数値を同等の文字列表現に変換します。また、整数は値の型です。独自のメモリ割り当て内にデータを保持する場合、データ型は値型です。
同じ関数名ToString()ですが、異なるタスクを実行します。