230

などのnullメソッドを安全に適用する前に、すべての文字列をテストするのは非常に面倒です...ToUpper()StartWith()

のデフォルト値が空の文字列である場合、テストする必要はなく、またはなどstringの他の値の型とより一貫していると感じます。さらに、理にかなっています。intdoubleNullable<String>

では、なぜ C# の設計者はnull、文字列の既定値として使用することを選択したのでしょうか?

注: これはこの質問に関連していますが、それをどうするかではなく、理由に重点を置いています。

4

15 に答える 15

324

文字列型のデフォルト値が空の文字列ではなく null なのはなぜですか?

string参照型であり、すべての参照型の既定値は ですnull

ToUpper()、StartWith() などのメソッドを安全に適用する前に、すべての文字列の null をテストするのは非常に面倒です...

これは、参照型の動作と一致しています。インスタンス メンバーを呼び出す前に、null 参照をチェックする必要があります。

文字列のデフォルト値が空の文字列である場合、テストする必要はなく、たとえば int や double などの他の値の型との一貫性がより高いと感じます。

以外の特定の参照型にデフォルト値を割り当てると、null一貫性がなくなります。

さらにNullable<String>、理にかなっています。

Nullable<T>値型で動作します。注目すべきは、元の.NET プラットフォームNullableでは導入されなかったため、そのルールを変更した場合、多くの壊れたコードがあったことです.( Courtesy @jcolebrand )

于 2013-01-15T12:17:51.433 に答える
40

Habibは正しいです-string参照型だからです。

しかし、もっと重要なことは、使用するたびにチェックする必要がないことです。ただし、誰かが関数に参照を渡した場合nullは、おそらくaをスローする必要があります。ArgumentNullExceptionnull

NullReferenceExceptionこれが問題です。文字列を呼び出そうとすると、フレームワークはとにかくをスローし.ToUpper()ます。nullパラメータとして関数に渡されるオブジェクトのプロパティまたはメソッドはに評価される可能性があるため、引数をテストしても、このケースが発生する可能性があることに注意してくださいnull

そうは言っても、空の文字列またはnullをチェックすることは一般的なことなので、これらはまさにこの目的のために提供String.IsNullOrEmpty()されます。String.IsNullOrWhiteSpace()

于 2013-01-15T12:20:44.967 に答える
24

拡張メソッドを書くことができます(その価値のために):

public static string EmptyNull(this string str)
{
    return str ?? "";
}

これで安全に動作します:

string str = null;
string upper = str.EmptyNull().ToUpper();
于 2013-01-15T12:22:38.600 に答える
14

空の文字列とnullは根本的に異なります。nullは値がないことであり、空の文字列は空の値です。

変数の「値」(この場合は空の文字列)について仮定するプログラミング言語は、null参照の問題を引き起こさない他の値で文字列を開始するのと同じくらい優れています。

また、その文字列変数へのハンドルをアプリケーションの他の部分に渡すと、そのコードには、意図的に空白の値を渡したのか、その変数の値を入力するのを忘れたのかを検証する方法がありません。

これが問題になるもう1つの場合は、文字列が関数からの戻り値である場合です。文字列は参照型であり、技術的にはnullと空の両方の値を持つことができるため、関数は技術的にnullまたは空を返すこともできます(そうすることを妨げるものは何もありません)。ここで、「値の欠如」には2つの概念、つまり空の文字列とnullがあるため、この関数を使用するすべてのコードは2つのチェックを実行する必要があります。1つは空用で、もう1つはnull用です。

つまり、単一の状態に対して1つの表現しかないことは常に良いことです。空とヌルに関するより広範な議論については、以下のリンクを参照してください。

https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value

ユーザー入力を処理するときのNULLと空

于 2013-01-15T13:27:44.850 に答える
7

callvirt基本的な理由/問題は、CLS 仕様 (言語が .net と対話する方法を定義する) の設計者が、クラス メンバーが を介してではなく直接呼び出す必要があることを指定できる手段を定義しなかったことです。 null 参照チェック; また、「通常の」ボクシングの対象とならない構造を定義する手段も提供しませんでした。

CLS 仕様でこのような手段が定義されていれば、.net は共通オブジェクト モデル (COM) によって確立されたリードに一貫して従うことができます。COM では、null 文字列参照は意味的に空の文字列と同等と見なされていました。同様にデフォルト値を定義するための値セマンティクスを持つと想定されるユーザー定義の不変クラス型。本質的には、 の各メンバーに対してString、たとえばのLengthように記述されます[InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }。このアプローチは、値のように動作する必要があるものに対して非常に優れたセマンティクスを提供しますが、実装の問題により、ヒープに格納する必要があります。このアプローチの最大の問題は、そのような型との間の変換のセマンティクスがObject少し曖昧になる可能性があることです。

別のアプローチは、継承ではなくObject、代わりにカスタムのボックス化およびボックス化解除操作 (他のクラス型との間で変換される) を持つ特別な構造型の定義を許可することでした。このようなアプローチでは、 string と同じように動作する class typeと、 typeの単一のプライベート フィールドを保持するNullableStringカスタム ボックス化された struct typeが存在します。をorに変換しようとすると、null 以外の場合、または null の場合に返されます。にキャストしようとすると、インスタンスへの null 以外の参照が参照を格納します (長さがゼロの場合は null を格納する可能性があります)。他の参照をキャストすると、例外がスローされます。StringValueStringStringNullableStringObjectValueString.EmptyStringNullableStringValue

文字列はヒープに格納する必要がありますが、概念的には、null 以外の既定値を持つ値型のように動作してはならない理由はありません。それらを参照を保持する「通常の」構造として格納することは、それらを「文字列」型として使用するコードにとっては効率的でしたが、「オブジェクト」にキャストするときに間接的で非効率的なレイヤーが追加されました。現時点で上記の機能のいずれかが .net に追加されるとは考えていませんが、将来のフレームワークの設計者はそれらを含めることを検討する可能性があります。

于 2013-01-15T16:55:12.637 に答える
6

C#の設計者が文字列のデフォルト値としてnullを使用することを選択したのはなぜですか?

文字列は参照型であるため、参照型はデフォルト値ですnull。参照型の変数は、実際のデータへの参照を格納します。

defaultこの場合、キーワードを使用しましょう。

string str = default(string); 

strはであるstringため、参照型であるため、デフォルト値はnullです。

int str = (default)(int);

strは、intであるため、値型であるため、デフォルト値はzeroです。

于 2013-01-15T12:20:16.530 に答える
5

文字列変数はインスタンスではなく参照であるためです。

デフォルトで Empty に初期化することは可能でしたが、ボード全体に多くの矛盾が生じていました。

于 2013-01-15T12:18:17.900 に答える
4

のデフォルト値stringが空の文字列の場合、テストする必要はありません

違う!デフォルト値を変更しても、それが参照型であり、誰かが明示的に参照を に設定できるという事実は変わりませんnull

さらにNullable<String>、理にかなっています。

真点。nullその機能を要求する代わりに、参照型を許可しない方が理にかなっていNullable<TheRefType>ます。

では、なぜ C# の設計者はnull、文字列の既定値として使用することを選択したのでしょうか?

他の参照型との一貫性。では、なぜnull参照型を許可するのでしょうか。おそらく C のように感じられるようにするためですが、Nullable.

于 2013-01-15T16:26:00.210 に答える
4

おそらく??、文字列変数を割り当てるときに演算子を使用すると、役立つかもしれません。

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.
于 2015-11-14T19:49:51.450 に答える
2

string は参照型であるため、参照型のデフォルト値は null です。

于 2013-01-15T21:09:09.447 に答える
2

String は不変オブジェクトです。つまり、値が与えられると、古い値はメモリから消去されず、古い場所に残り、新しい値は新しい場所に置かれます。したがって、 のデフォルト値が である場合String a、最初の値が与えられたときにメモリ内String.Emptyのブロックが無駄になります。String.Empty

ごくわずかに見えますが、文字列の大きな配列をデフォルト値の で初期化するときに問題になる可能性がありますString.Empty。もちろん、StringBuilderこれが問題になる場合は、いつでも可変クラスを使用できます。

于 2013-01-15T19:11:09.360 に答える
0

Nullable 型は 2.0 まで登場しませんでした。

言語の初期に null 許容型が作成されていた場合、文字列は null 非許容で文字列? nullable だったでしょう。しかし、下位互換性のためにこれを行うことができませんでした。

多くの人が ref 型または非 ref 型について話しますが、文字列は通常とは異なるクラスであり、それを可能にする解決策が見つかったはずです。

于 2015-02-17T15:11:16.717 に答える
0

キーワードは他の値型string宣言とまったく同じように見えるため、混乱する可能性がありますが、実際にはこの質問で説明されているようにエイリアスです。 また、Visual Studio の濃い青色と小文字の最初の文字は、それが.System.String
struct

于 2013-01-15T14:19:15.687 に答える