オプションのパラメーターのデフォルト値としてString.Emptyを使用することはできません


89

私はビル・ワーグナーによるEffective C#を読んでいます。で項目14 -重複の初期化ロジックを最小化し、彼は、コンストラクタに新しいオプションのパラメータ機能を使用して、次の例を示します。

public MyClass(int initialCount = 0, string name = "")

彼がの""代わりに使用したことに注意してくださいstring.Empty
彼はコメントします:

(上記の例では)2番目のコンストラクターが、より慣習的なではなく、nameパラメーターのデフォルト値に ""を指定したことに注意してくださいstring.Empty。これstring.Emptyは、がコンパイル時の定数ではないためです。これは、文字列クラスで定義された静的プロパティです。コンパイル定数ではないため、パラメータのデフォルト値には使用できません。

string.Emptyすべての状況でstaticを使用できない場合、それはその目的を無効にしませんか?空の文字列を参照するシステムに依存しない手段があることを確認するためにそれを使用すると思いました。私の理解は間違っていますか?ありがとう。

更新
ただフォローアップコメント。MSDNによると:

オプションの各パラメータには、定義の一部としてデフォルト値があります。そのパラメーターに引数が送信されない場合、デフォルト値が使用されます。デフォルト値は定数でなければなりません。

次にSystem.Environment.NewLine、どちらも使用できません。または、新しくインスタンス化されたオブジェクトをデフォルト値として使用できません。私はまだVS2010を使用していませんが、これは残念です。


2
異なるプラットフォームでの空の文字列の表現方法の違いについては知りません。改行のようなものではありません。
Tom Cabanski、2010

そうだと思っていたので、コードで見栄えを良くしただけなのでしょうか。
Mikeyg36 2010

1
「システム」ではなくCLRが、「」が空の文字列であるかどうかを決定する要素です。したがって、 ""は、システムに依存しない、準拠したCLR実装の文字列を参照する方法であると想定しても安全だと思います。
Chris Taylor

「システムに依存しない」?ええと、システム固有の「」とは対照的に?(???)
Qwertie 2010

MSDNによると、このフィールドの値は長さ0の文字列 ""です。多くの人が指摘しているように、それは明らかにプラットフォームの独立性とは何の関係もありません。それでも、なぜそれを使用する必要があるのか​​、人々はまだ本当に知らないようです!
Mikeyg36 2010

回答:


65

C#2.0コンパイラの時点では、String.Emptyとにかくほとんど意味がありません。実際、多くの場合それは悲観化です。コンパイラはへの参照をインライン化""できますが、と同じことはできませんString.Empty

C#1.1では、すべてが空の文字列を含む独立したオブジェクトを多数作成することを回避することが有用でしたが、それらの時代は終わりました。 ""正常に動作します。


7
.NET 1.1でさえ、独立したオブジェクトの「ロット」を作成しません。この点での1.1と2.0の違いの詳細は思い出せませんが、文字列リテラルのインターンが2.0でのみ導入されたようではありません。
Jon Skeet、2010

説明をありがとう。私は周りを見回しましたが、C#2.0での変更点の適切な要約は見つかりませんでしたが、以前に読んだことがあると確信しています。2008年のStackOverflowの回答には、より技術的な情報へのリンクがいくつかありました。 stackoverflow.com/questions/151472/...
アンディ・モーティマー

1
私はこれにうなずきますが、文字列を使う意味がほとんどないので嫌いです。見た目はすっきりしていますが、それは私の個人的な見解です。多くの場所の文字列があります。空は使用できません。それらの場合、 ""を使用しても問題ありません
xximjasonxx

14
空の文字列をString.Emptyですばやく特定する方が、 ""を2回参照するよりも、アポストロフィなどが隠れていないことを確認するよりもはるかに簡単です。説明は+1。
NotMe

11
+1クリス。また、VSでは、 ""の使用法を検索することはできません(コメントやマークアップを含むすべてのテキストの一致を返す標準の検索を実行する場合を除きます)。string.Emptyを使用して、コード固有の使用法を検索できます。
MutantNinjaCodeMonkey

53

オプションのパラメーター値として本当に使用したい場合は、空の文字列に独自の定数を定義するのを妨げるものは何もありません。

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[余談ですが、一般的に好まString.Emptyれる理由の1つ""は、他の回答では言及されていませんが、肉眼では事実上見えないさまざまなUnicode文字(ゼロ幅ジョイナーなど)があるためです。したがって、次のように表示されるもの""は必ずしも空の文字列であるとString.Emptyは限りませんが、使用しているものを正確に把握できます。これは一般的なバグの原因ではないことを認識していますが、それは可能です。]


2
非表示の識別子文字もあるので、String_Emptyのように見えるものは必ずしもそうではありません。Unicode規格には、セキュリティに関する考慮事項についてほとんど無視されている章があります。
ジムバルター2015

25

元の質問から:

空の文字列を参照するシステムに依存しない手段があることを確認するためにそれを使用すると思いました。

空の文字列はシステムによってどのように異なるのでしょうか?常に文字のない文字列です!false が返される実装を見つけたら、私は本当に怖いでしょうstring.Empty == "":)これはのようなものと同じではありませんEnvironment.NewLine

Counter Terroristのバウンティポストから:

String.Emptyを次のC#リリースのデフォルトパラメータとして使用できます。:D

まあそれは確かに起こりません。

私も個人的には非常に異なるデフォルトのメカニズムが好きでしたが、オプションのパラメーターの動作方法は最初から.NETにありました。これは常に定数をメタデータに埋め込むことを意味し、呼び出しコードがその定数を呼び出しにコピーできるようにします対応する引数が提供されていない場合のサイト。

string.Empty、それはだ本当に無意味-使用して""、あなたがやりたいだろう。それがあることを痛いが、文字列リテラルを使用しますか?(私はどこでもリテラルを使用します-決して使用しませんstring.Emptyが、それは別の引数です。)

それがこの質問について私を驚かせるものです-苦情実際に実際の問題を引き起こさない何かを中心に展開します。デフォルトは実際には変化する可能性があるため、実行時にデフォルトを計算する場合に、より重要です。たとえば、DateTimeパラメータを使用してメソッドを呼び出し、デフォルトで「現在の時刻」にしたい場合を想像できます。現在のところ、私が知っている漠然としたエレガントな回避策は次のとおりです。

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

...しかし、それが常に適切であるとは限りません。

結論として:

  • これがC#の一部になることは間違いありません
  • ために string.Emptyそれの無意味とにかく
  • 必ずしも同じ値であると限らない他の値の場合、それは本当に苦痛になる可能性があります

これは実際には問題を修正する良い方法です。同じことを使用して、Environment.Newline..のような他のデバイス依存変数を保持/設定することができます。この例で欠けているのは、変数のnullのチェックであり、開発者に例外をスローして、null可能である一方で、受け入れられません。if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}またはそのようなもの。しかし、私はこれが本当に好きです!あなたのやり方でそれをすることに対する他の警告?
MaxOvrdrv 2014年

@MaxOvrdrv:nullにしてエラーにしたくない-重要なのは、nullの場合はデフォルトを計算することです。警告は、それ自体がnullを有効な値として渡すことを許可しないことです。
Jon Skeet

あなたはそれについて完全に正しいです。私の悪い。-そして、はい、それが唯一の真の警告ではないでしょう...それはそれほど悪くはありません。繰り返しますが、私はこのソリューションが本当に好きです!:)それを投稿してくれてありがとう!:)
MaxOvrdrv 2014年

7

string.Emptyを使用することはありません。意味がわかりません。プログラミングに慣れていない人にとっては簡単になるかもしれませんが、それでもそれが役立つとは思えません。


2
たぶん、混乱""を防ぐこと" "ができるかもしれませんが、それだけのことはありません" "
グレッグ

8
これらのニーズの違いが分からない人は、より良いメガネを使うか、画面の解像度を下げる必要があります。私は視力が悪く、間違いを犯したことを思い出すことができません(その両方を含む多くのコードで作業する必要があります)。
Hans Olsson

2
string.Emptyは、プログラマーの正確な意図を見つけるのに役立ちます。「笑」が、忘れてしまった...この場合には無限の可能性と、文字列があり、空には便利な来て、より良い仕事をして「プログラマの意図は、このような変数を初期化することだった場合、何の意図については何も教えてくれない」
usefulBee

4

文字列の背後にある考えは私は思います。異なるプラットフォームでの表現方法に違いがある改行とは異なります。デフォルトのパラメータでは使用できません。ただし、WindowsとLinux上のMonoなどのポートを移植しても問題は発生しません。


5
ポイントは、一部の人々がString.Emptyより読みやすいと考えているということであるとあなたはおそらく正しいと思います。。。個人的には、それは少しくだらないことだと思います。""おそらく最も一般的な文字列であり、誰もがそれを10億回見たことがあります。String.Emptyが存在するのと同じくらい便利ですInt32.Zero
Tim Goodman

3

FYIとして、同じ制約が属性コンストラクターに渡される値に課されているように見えます-それらは定数でなければなりません。string.emptyは次のように定義されているので:

public static readonly string Empty

実際の定数ではなく、使用することはできません。


1

string.Empty読みやすさのためだけに使用しています。

他の誰かが後で私のコードを読んだり変更したりする必要がある場合、彼らは私が何かをチェックしたり、空の文字列に設定したりするつもりだったことを知っています。ちょうどを使用して""をすると、必要な文字列を入力するのを忘れた可能性があるため、バグや混乱を引き起こす可能性があります。

例えば:

if(someString == string.Empty)
{

}

if(someString == "")
{

}

最初のifステートメントは、私にとっては非常に意図的で読みやすいように思えます。ただし、これは単なる設定なので、""代わりにを使用する必要があることで、列車のスマッシュは実際にはわかりませんstring.Empty


-2

おそらく、この問題の最善の解決策は、この方法のオーバーロードです。

public static void PrintString() 
{ 
    PrintString(string.Empty);
}

3
上記の質問にどのように答えますか?
Pranav Singh 2013

1
オプションのパラメーターのデフォルト値はどのように役立ちますか?
デフォルトのロケール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.