デフォルトの文字列初期化:NULLまたは空?[閉まっている]


130

文字列は常にNULLに初期化してきました。NULLは値がないことを意味し、 ""またはString.Emptyは有効な値です。String.Emptyがデフォルト値と見なされるか、値を表さないコードの例を最近見ました。これは奇妙な印象を与えます。c#に新しく追加されたnull許容型を使用すると、NULLを使用せずに「値なし」を表すことにより、文字列を後方に進めているようです。

デフォルトのイニシャライザとして何を使用していますか、またその理由は何ですか?

編集:私のさらなる考えにさらに答えに基づいて

  1. エラー処理の回避値をnullにしてはいけないのに、そもそもなぜそれが設定さNULLれたのですか?おそらく、コードベースの残りの部分全体をカバーするよりも、エラーが発生した場所でエラーを特定する方が良いでしょうか?

  2. nullチェックの回避コードでnullチェックを行うことにうんざりしている場合は、nullチェックを抽象化する方が良いのではないでしょうか。おそらく、それらをNULL安全にするために文字列メソッドをラップ(または拡張!)常に使用String.Emptyしていて、nullがシステムに機能している場合はどうなりますNULLか?とにかくチェックを追加し始めますか?

怠惰だという意見に戻らざるを得ません。nullデータベースで''の代わりに ''を使用した場合、どのDBAも9つの方法で愚かなことをするでしょう。私は同じ原則がプログラミングにも当てはまると思います。価値を表すのString.Emptyではなく、頭の中で使用している人を叩く人がいるはずNULLです。

関連する質問


「正気」?私が知っているダナではいけません。
vfilby 2008年

@ジョエル、ジムやGIRについて何の手がかりもない人がいることに驚かされます。それは純粋な良さではありませんが、そこには素晴らしいユーモアのナゲットがあります。
vfilby 2008年

私は知っていますが、それ以外のふりをするのは楽しいこともあります。
Dana the Sane

1
MVCフォームコレクションまたはセッション変数でこの問題に何度も遭遇しましたが、最も有用なのは、nullをString.Emptyに変換することでした。略記し、必要な文字列操作を適用します。例えば。(アイテム?? String.Empty).Trim()。ToUpper()
sonjz

4
これは建設的ではありませんか?
nawfal 2013年

回答:


111

「空」とNULLを区別するための+1。「空」は「有効だが空白」を意味し、「NULL」は「無効」を意味することに同意します。

だから私はこのようなあなたの質問に答えたいと思います:

たとえばユーザーのミドルネームなど、変更される場合と変更されない場合がある有効なデフォルト値が必要な場合はです。

次のコードで値が明示的に設定されていない場合は、エラーの場合はNULL


11
NULLと空を区別することは、2つの間に実際に違いがある場合に最適です。ただし、違いがない場合が多いため、同じものを表す方法が2つあると責任が生じます。
Greg Smalter 08年

6
@Greg:多様性には混乱の可能性があると私は同意しますが、それは素晴らしい資産にもなる可能性があります。有効な値と無効な値を区別するために ""またはNULLを記述するという単純で一貫した規則は、コードを理解しやすくします。これが、ブール値を常に「if(var)」で、ポインタを「if(var!= NULL)」で、整数を「if(var!= 0)」でテストする理由です。これらはすべてコンパイラにとって同じ意味です。しかし、彼らは私のコードを保守する貧しい開発者を助ける追加情報を運びます。
Adam Liss、2010年

32

MSDNによると:

文字列をのEmpty代わりに値で初期化nullすることにより、NullReferenceException発生する可能性を減らすことができます。

IsNullOrEmpty()それにもかかわらず、常に使用することは良い習慣です。


45
例外の可能性を減らしているからといって、例外が発生してはならないというわけではありません。コードがそこにある値に依存している場合、それは例外をスローするはずです!
rmeador 2008年

1
確かに、そこには議論はありません。OTOH、文字列を一緒に追加するだけの場合...コーディングスタイル、経験、状況に依存すると思います。
Tomalak 2008年

これは主に私が使用するもので、どちらを使用するかを区別します。
PositiveGuy

3
.NET Framework 4+のIsNullOrWhiteSpace()を忘れないでください
Coops

13

文字列をまったく初期化しないのはなぜですか?変数を宣言するときに変数を初期化する必要はありません。IMOは、割り当てている値がコードブロックのコンテキストで有効な場合にのみ初期化する必要があります。

私はこれをよく見ます:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else
{
  name = "bar";
}

return name;

nullに初期化しないことも同様に効果的です。さらに、ほとんどの場合、値を割り当てる必要があります。nullに初期化することにより、値を割り当てないコードパスを見逃す可能性があります。そのようです:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else if (othercondition)
{
  name = "bar";
}

return name; //returns null when condition and othercondition are false

nullに初期化しないと、コンパイラはすべてのコードパスに値が割り当てられるわけではないことを示すエラーを生成します。もちろん、これは非常に単純な例です...

Matthijs


ほとんどすべてのC#プログラマーが使用していると思いますVisual Studioでは、2番目の状況(なし= null)は警告を生成します。これは、あなたが述べた理由とまったく同じです。文字列のデフォルト値がnullかどうかは関係ありません。すべてのコードパスを通じて割り当てを保証しない場合、IDE(および/または基礎となるコンパイラ[?])が警告を生成します。警告はコンパイルを妨げるものではありませんが、それらはまだ存在します-簡単に解決できるものを残すと、プログラマーの注意を引く可能性がある他の
コード

私の知る限りでは、最初の状況はnametoの初期化なしで完全に満足しますnull(警告なし)。すべてのコードパスが値を割り当てるため、nameそこで初期化する必要はありません
コードジョッキー

8

実際に文字列処理ソフトウェアではないほとんどのソフトウェアでは、プログラムロジックは文字列変数の内容に依存すべきではありません。私がプログラムでこのようなものを見たときはいつでも:

if (s == "value")

気分が悪い。このメソッドに文字列リテラルがあるのはなぜですか?設定とはs?ロジックが文字列の値に依存することを知っていますか?機能するためには小文字でなければならないことを知っていますか?使用するように変更してこれを修正する必要がありますString.Compareか?私はそれを作成しEnumて解析する必要がありますか?

この観点から、かなり単純なコードの哲学に到達します。可能な限り、文字列の内容を調べることは避けます。文字列の比較String.Emptyは、実際にはそれをリテラルと比較する特別な場合にすぎません。本当に必要な場合を除いて、これは避けるべきことです。

これを知っているので、コードベースに次のようなものが表示されても点滅しません。

string msg = Validate(item);
if (msg != null)
{
   DisplayErrorMessage(msg);
   return;
}

私たちはそれよりも良いコードを書いているので、それValidateは決して戻らないでしょうString.Empty

もちろん、世界の他の国はこのように機能しません。プログラムがユーザー入力、データベース、ファイルなどを処理する場合、他の哲学を考慮する必要があります。そこで、混乱の秩序を課すのはあなたのコードの仕事です。その順序の一部は、空の文字列がString.Emptyいつ意味するのか、いつ意味するのかを知ることnullです。

(私が私のお尻から話しているのではないことを確認するために、私はコードベースで `String.IsNullOrEmpty 'を検索しました。それが発生する54のすべては、ユーザー入力を処理し、Pythonスクリプトから値を返し、外部APIなど)


6

これは実際にはC#言語の大きな穴です。nullにできない文字列を定義する方法はありません。多くの場合NULLとString.Emptyは同じことを意味するので、これは、あなたが説明しているものと同じくらい単純な問題を引き起こし、プログラマーが彼らがする必要のない決定をすることを強います。そのため、後で他のプログラマーにNULLとString.Emptyの両方を処理するように強制する可能性があり、これは面倒です。

より大きな問題は、データベースではC#文字列にマップするフィールドを定義できるが、データベースフィールドはNOT NULLとして定義できることです。したがって、C#型を使用してSQL Serverでvarchar(100)NOT NULLフィールドを正確に表す方法はありません。

仕様番号などの他の言語ではこれが可能です。

私の意見では、C#がnullを許可しない文字列を定義できないことは、以前のnullを許可するintを定義できないことと同じくらい悪いことです。

質問に完全に答えるために:デフォルトの初期化には常に空の文字列を使用します。これは、データベースのデータ型がどのように機能するかに似ているためです。(編集:このステートメントは非常に不明確でした。「NULLが不必要な状態の場合、デフォルトの初期化に空の文字列を使用します。NULLが不必要な状態になった場合にデータベース列をNOT NULLとして設定したのと同じ方法です。同様に、DB列の多くはNOT NULLとして設定されているので、それらをC#文字列に取り込むと、文字列は空になるか、値が設定されますが、NULLになることはありません。つまり、文字列をNULLに初期化するだけですnullにString.Emptyの意味とは異なる意味があり、そのケースが一般的ではない場合(ただし、ここの人々はこのケースの正当な例を示しています)。)


String.Emptyの使用は、データベース文字列が定義される方法の1つにのみ似ています。値がないことを表すためにnullを使用することは、nvarcharがnullの場合とはるかに一致します。''を使用して値を表さない場合、そのDBAは9つの方法で愚かなことをするでしょう。
vfilby 2008年

実際には、グレッグ、あなたはそれを間違った方法で持っています。nullを保持できず、null可能な列にマップできないため、「データベースの種類はどのように機能する」かは、nullできない値型です。規約では、任意の文字列を任意のvarchar列にマップできます。
Tor Haugen

私の最後の主張は十分に明確ではありませんでした。ほとんどの場合、データベースの列はNOT NULLです(空の文字列とNULLの意味には違いがないため)。そのため、Nullを格納しないことで文字列を同じように維持しようとします。
Greg Smalter、2008年

5

場合によります。

値が欠落しているかどうかを確認できる必要がありますか(定義されていない可能性はありますか)?

空の文字列は、その文字列の使用に有効な値ですか?

両方に「はい」と答えた場合は、nullを使用する必要があります。そうしないと、「値なし」と「空の文字列」の違いを見分けることができません。

値がないかどうかを知る必要がない場合は、空の文字列を使用するとどこでもnullチェックをスキップできるため、おそらく安全です。



3

「」またはnullに設定します。常にString.IsNullOrEmptyを使用してチェックするため、どちらでも問題ありません。

しかし、私の内側のオタクは、適切な値を得る前にnullに設定する必要があると言っています...



2

これがエラー回避技術である可能性はありますか(推奨されるかどうか)。""はまだ文字列なので、文字列関数を呼び出して、NULLの場合に例外が発生する可能性はありますか?


1
それは私が通常聞く言い訳です、ただ怠惰のように聞こえます。「この値をチェックしたくないので、近道をします」と私には思えます。
vfilby 2008年

ええ、私は反対していません。そこエラーチェックコードの量を低減することがいいです、いくつかの状況であってもよいが、効果がない関数呼び出しが...どちらかの最大のではないかもしれない
ダナセイン

2

私は常にそれらをとして初期化しますNULL

私はいつもstring.IsNullOrEmpty(someString)その値をチェックするために使用します。

シンプル。


1

状況によります。ほとんどの場合、文字列を使用するたびにnullチェックを実行したくないので、String.Emptyを使用します。これにより、コードが大幅に簡素化され、不要なNullReferenceExceptionクラッシュが発生する可能性が低くなります。

文字列がnullに設定されるのは、それが設定されているかどうか、および空の文字列がどこに設定するのに有効かを知る必要がある場合のみです。実際には、これらの状況はまれです。


1

空の文字列は値です(偶然にも文字が含まれていないテキストの一部です)。nullは値がないことを示します。

変数が実際の値を指していない、または含まれていないことを示す場合は、変数をnullに初期化します(値が意図されていない場合)。


1

Tomalak応答を繰り返しますが、文字列変数をnullの初期値に割り当てると、変数は文字列オブジェクトではなくなることに注意してください。C#のオブジェクトと同じです。したがって、変数のメソッドまたはプロパティにアクセスしようとして、それが文字列オブジェクトであると想定している場合、NullReferenceException例外が発生します。


1

nullは、値がオプションの場合にのみ使用してください。値がオプションではない場合(「名前」や「アドレス」など)、値をnullにすることはできません。これは、POCOとユーザーインターフェイスだけでなく、データベースにも当てはまります。Nullは「この値はオプションであり、現在は存在しない」ことを意味します。

フィールドがオプションでない場合は、空の文字列として初期化する必要があります。これをnullとして初期化すると、オブジェクトが無効な状態になります(独自のデータモデルでは無効)。

個人的には、デフォルトでは文字列をnullにできないようにしたいのですが、「文字列?」を宣言した場合にのみnullにできます。おそらくこれはより深いレベルでは実現可能でも論理的でもありません。わからない。



0

割り当てられていない(またはプログラムフローのこの場所で発生していない)値にnullを使用しない理由はないと思います。区別したい場合は、== nullがあります。特定の値をチェックするだけで、それがnullか別のものかを気にしない場合は、String.Equals( "XXX"、MyStringVar)で問題ありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.