String.Empty
.NET では、との違いは何ですか。""
また、それらは互換性がありますか、それともString.Empty
、問題にならないことを保証する平等に関する根本的な参照またはローカリゼーションの問題がありますか?
18 に答える
バージョン 2.0 より前の .NET では、オブジェクトrefを作成せずにオブジェクト""
を作成するため、効率が向上します。string.Empty
string.Empty
.NET のバージョン 2.0 以降では、すべての出現箇所""
が同じ文字列リテラルを参照します。つまり、""
は と同等ですが.Empty
、それでも ほど高速ではありません.Length == 0
。
.Length == 0
は最速のオプションですが、.Empty
コードが少しきれいになります。
詳細については、.NET 仕様を参照してください。
String.Emptyと""の違いは何ですか?それらは交換可能ですか?
string.Empty
は読み取り専用フィールド""
ですが、はコンパイル時定数です。動作が異なる場所は次のとおりです。
C#4.0以降のデフォルトのパラメーター値
void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
//... implementation
}
switchステートメントのケース式
string str = "";
switch(str)
{
case string.Empty: // Error: A constant value is expected.
break;
case "":
break;
}
属性引数
[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type
以前の回答は .NET 1.1 に対して正しかったです (リンクされた投稿の日付を見てください: 2003)。.NET 2.0 以降では、基本的に違いはありません。とにかく、JIT はヒープ上の同じオブジェクトを参照することになります。
C# 仕様によると、セクション 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx
各文字列リテラルが必ずしも新しい文字列インスタンスになるとは限りません。文字列等値演算子 (セクション 7.9.7) に従って等価である 2 つ以上の文字列リテラルが同じアセンブリに現れる場合、これらの文字列リテラルは同じ文字列インスタンスを参照します。
Brad Abramの投稿のコメントで誰かがこれについて言及しています
要約すると、"" と String.Empty の実際の結果はゼロです。JITは最終的にそれを理解します。
個人的には、JIT は私よりずっと賢いことがわかったので、そのようなマイクロコンパイラーの最適化をあまり賢くしないようにしています。JIT は、for() ループを展開し、冗長なコードを削除し、メソッドをインライン化するなど、私や C# コンパイラが事前に予測するよりも適切なタイミングで適切に処理します。JITに仕事をさせてください:)
String.Empty
はconstですが、読み取り専用フィールドです。これは、定数ではないため、switch ステートメントで使用できないことを意味します。""
String.Empty
もう 1 つの違いは、String.Empty はより大きな CIL コードを生成することです。"" と String.Empty を参照するコードは同じ長さですが、コンパイラはString.Empty 引数の文字列連結 (Eric Lippert のブログ投稿を参照) を最適化しません。以下の同等の機能
string foo()
{
return "foo" + "";
}
string bar()
{
return "bar" + string.Empty;
}
この IL を生成します
.method private hidebysig instance string foo() cil managed
{
.maxstack 8
L_0000: ldstr "foo"
L_0005: ret
}
.method private hidebysig instance string bar() cil managed
{
.maxstack 8
L_0000: ldstr "bar"
L_0005: ldsfld string [mscorlib]System.String::Empty
L_000a: call string [mscorlib]System.String::Concat(string, string)
L_000f: ret
}
私は1 つの単純な、しかし明白ではない理由で
String.Empty
はなく、使用する傾向があります。同じではありません。最初のものには、実際には 16 個のゼロ幅の文字が含まれています。明らかに有能な開発者は、コードに幅ゼロの文字を入れようとはしませんが、もし入ってしまったら、メンテナンスの悪夢になる可能性があります。""
""
""
ノート:
この例ではU+FEFFを使用しました。
SOがそれらの文字を食べるかどうかはわかりませんが、多くのゼロ幅文字の1つで試してみてください
https://codegolf.stackexchange.com/のおかげで、私はこれに出くわしました
上記の回答は技術的には正しいですが、コードを読みやすくし、例外の可能性を最小限に抑えるために、実際に使用したいのはString.IsNullOrEmpty(s)です。
"" のすべてのインスタンスは、同じ、インターンされた文字列リテラルです (またはそうである必要があります)。したがって、 "" を使用するたびに新しいオブジェクトをヒープにスローするのではなく、インターンされた同じオブジェクトへの参照を作成するだけです。そうは言っても、string.Empty の方が好きです。コードが読みやすくなると思います。
String.Empty はオブジェクトを作成しませんが、 "" は作成します。ただし、ここで指摘されているように、違いは些細なことです。
それは問題ではありません!
これに関する過去の議論:
http://www.codinghorror.com/blog/archives/000185.html
string mystring = "";
ldstr ""
ldstr
メタデータに格納されている文字列リテラルに新しいオブジェクト参照をプッシュします。
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
静的フィールドの値を評価スタックにプッシュします
IMHOの方が明確でVBっぽくないので、String.Empty
代わりに使用する傾向があります。""
ここにいる全員が、いくつかの優れた理論的説明を提供してくれました。私も同じような疑問を持っていました。そこで、基本的なコーディングを試みました。そして、私は違いを見つけました。これが違いです。
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
したがって、「Null」は絶対に無効であることを意味し、「String.Empty」は何らかの値が含まれているが空であることを意味するようです。