web-dev-qa-db-ja.com

.ToString()がnull値を持つnull許容intで正常に機能するのに、null文字列の.ToString()がnullエラーを引き起こすのはなぜですか?

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文字列では使用できませんか?

69
CptSupermrkt

stringタイプのnullは実際には何も指していないため、メモリ内にオブジェクトはありません。
だが int? type(nullable)は、値がnullに設定されていても、一部のオブジェクトを指します。
Jeffrey Richterの「C#を介したCLR」を読むと、DB nullでの作業をより便利にするために、null許容型は、いくつかのカプセル化されたロジックを持つ一般的な型のファサードクラスにすぎないことがわかります。

Null許容型については、 msdn を確認してください。

89
Johnny_D

Nullable<int>structであり、実際にnullにすることはできません。したがって、「null」構造体のメソッド呼び出しは引き続き機能します。

_cost == nullを有効な式にする「コンパイラマジック」があります。

32
Hans Kesting

int?は実際にはそれ自体がオブジェクトではありませんが、Nullable<int>オブジェクトです。

したがって、int? _Costを宣言すると、実際にはNullable<int> _Costが宣言され、_Cost.Valueのプロパティはundefinedであり、_Costオブジェクト自体ではありません。

intbooldecimalなどのnon nullable型を簡単に使用することは、実際には構文上の砂糖です。

[〜#〜] msdn [〜#〜] によると:

構文T?System.Nullable<T>の省略形であり、Tは値の型です。 2つの形式は交換可能です。

14
Asif Mushtaq

文字列は参照型ですが、null許容intは値型です。ここに違いの良い議論があります http://www.albahari.com/valuevsreftypes.aspx

4
Tom Highfield

Nullableは実際には、HasValueとValueの2つのプロパティを公開する構造体です。これを行うと、エラーが発生します。

int? i = null;
i.Value.ToString()

あなたのintかどうかを確認するには?アクセスできる値があるi.HasValue

2

理由は簡単です。 _int?_または _Nullable<int>_structまたは 値のタイプnullにすることはできません

だから私たちが行うとどうなりますか:

_int? _cost = null;
_

__cost_には、ValueHasValueの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

1
Habib

その理由は、コンパイラがプリミティブデータ型を検出すると、対応するオブジェクトにラップすることです。 toString()メソッドの呼び出しは、ここでは間接的な呼び出し(ラップしてからメソッドを呼び出す)であり、例外はそこで処理されます。文字列の場合は、メソッドを直接呼び出します。 nullを指す場合、メソッドは例外をスローします。

1
Sashi Kant
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error

System.Stringのメンバーである関数 ToString() を呼び出しているため、エラーが発生します。この関数は、System.Stringのこのインスタンスを返します。実際の変換は行われません。また、Stringは参照型です。参照型には、データを保持する別のメモリ位置へのポインタが含まれています。

TextBox1.Text = selectedItem.Cost.ToString(); //no error

System.Integerのメンバーである関数 ToString() を呼び出しているため、エラーは発生しません。この関数は、このインスタンスの数値を同等の文字列表現に変換します。また、整数は値の型です。独自のメモリ割り当て内にデータを保持する場合、データ型は値型です。

同じ関数名ToString()ですが、異なるタスクを実行します。

String.ToStringメソッド

Int32.ToStringメソッド

値タイプと参照タイプ

0
Angkor Wat