回答:
バージョン2.0より前の.NETでは、""
オブジェクトをstring.Empty
作成し、オブジェクト参照を作成しないため、string.Empty
より効率的です。
.NETバージョン2.0以降では、はすべて""
同じ文字列リテラルを参照します。つまり、""
と同等ですが.Empty
、ほど高速ではありません.Length == 0
。
.Length == 0
は最速のオプションですが、.Empty
コードが少しすっきりします。
string.IsNullOrEmpty( stringVar )
。
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ステートメントのcase式
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
String.Empty
、ほとんどの場合、引数としてを渡すことができるためです。すべての例がそれyou simply can't put a (run-time) "value" into (compile-time) metadata
を示しており、それが例が示すことを目指しているものです。
以前の回答は.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つ以上の文字列リテラルが同じアセンブリ内にある場合、これらの文字列リテラルは同じ文字列インスタンスを参照します。
誰かがブラッド・エイブラムの投稿のコメントでこれについても言及しています
要約すると、 ""とString.Emptyの実際の結果はnilです。JITは最終的にそれを理解します。
私は個人的に、JITが私よりもはるかに賢いので、そのようなマイクロコンパイラの最適化をあまり賢くしないようにしています。JITはfor()ループを展開し、冗長なコード、インラインメソッドなどを、IまたはC#コンパイラーが事前に予想できるよりも適切かつ適切なタイミングで削除します。JITにその仕事を任せましょう:)
String.Empty
は読み取り専用フィールド""
ですが、constです。つまりString.Empty
、定数ではないため、switchステートメントでは使用できません。
default
キーワードの出現により、偶然の変更を防ぎ、偶然の変更を防ぎ、コンパイル時の定数を持たせることができるようになりましたが、正直なところ、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
}
"bar " + (ok ? "" : "error")
上記の答えは技術的には正しいですが、コードを読みやすくし、例外が発生する可能性を最小限にするために、実際に使用したいのはString.IsNullOrEmpty(s)です。
--foo=$BAR
場合、おそらく環境変数を設定し忘れていることと、フラグをまったく渡していないことの違いを見つけたいでしょう。string.IsNullOrEmpty
多くの場合、入力を適切に検証していないか、奇妙なことをしているコード臭です。実際にnull
、またはMaybe / Optionタイプのようなものを使用するつもりである場合、通常は空の文字列を受け入れるべきではありません。
私が使用する傾向があるString.Empty
のではなくを""
1つの簡単なため、まだ明らかでない理由:
""
と""
同じではありません、最初のものは実際にそれに16個のゼロ幅文字を持っています。明らかに、有能な開発者がコードに幅ゼロの文字を入れようとはしていませんが、そこに入ると、メンテナンスの悪夢になる可能性があります。
ノート:
この例ではU + FEFFを使用しました。
SOがそれらの文字を食べるかどうかはわかりませんが、多くのゼロ幅文字の1つを試してみてください
String.Empty
よりも使用してください""
。
これはメモリ使用量よりも速度の点で優れていますが、役立つヒントです。
""
リテラルのでリテラルとして機能します次のとおりです。最初の使用時にそれが作成され、以下の用途のためにその参照が返されます。""
何回使用しても、に格納されるのは1つのインスタンスのみです。ここにはメモリのペナルティはありません。問題は、""
が使用されるたびに、比較ループが実行され、""
すでにがインターンプールにあるかどうかをチェックすること です。一方、は、.NET Frameworkのメモリゾーンに格納されているString.Empty
への参照です。 VB.NETとC#アプリケーションの同じメモリアドレスを指しています。それで、 その参照があるときに必要になるたびに参照を検索する理由""
String.Empty
""
String.Empty
?
リファレンス:String.Empty
vs""
""のすべてのインスタンスは、同じインターン文字列リテラルです(またはそうである必要があります)。したがって、 ""を使用するたびにヒープに新しいオブジェクトをスローするのではなく、同じインターンオブジェクトへの参照を作成するだけです。そうは言っても、私はstring.Emptyを好みます。コードが読みやすくなると思います。
それは問題ではありません!
これに関する過去の議論:
http://www.codinghorror.com/blog/archives/000185.html
Eric Lippert は次のように書いています(2013年6月17日):
「C#コンパイラで最初に取り組んだアルゴリズムは文字列連結を処理するオプティマイザでした。残念ながら、去る前にこれらの最適化をRoslynコードベースに移植できませんでした。うまくいけば誰かがそれに着く!」
2019年1月現在のRoslyn x64の結果をいくつか示します。このページの他の回答についての意見の一致にもかかわらず、現在のx64 JITがこれらすべてのケースを同じように扱っているとは思えません。
ただし、特にこれらの例の1つだけが実際にを呼び出すことString.Concat
に注意してください。これは、(最適化の監視とは対照的に)正確性の理由がわかりにくいためだと思います。他の違いは説明するのが難しいようです。
default(String)+ {default(String)、 ""、String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
"" + {default(String)、 ""、String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty + {default(String)、 ""、String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
Entity Frameworkの観点から見ると、EFバージョン6.1.3は検証時にString.Emptyと ""を異なる方法で処理するように見えます。
string.Emptyは検証の目的でnull値として扱われ、必須(属性付き)フィールドで使用された場合、検証エラーをスローします。ここで、 ""は検証に合格し、エラーをスローしません。
この問題はEF 7以降で解決される可能性があります。参照:-https : //github.com/aspnet/EntityFramework/issues/2610)。
編集:[必須(AllowEmptyStrings = true)]はこの問題を解決し、string.Emptyが検証できるようにします。
コードを視覚的にスキャンしているとき、 ""は文字列の色分けと同じように色分けされて表示されます。string.Emptyは、通常のクラスメンバーアクセスのように見えます。一見すると、「」を見つけたり、意味を直感的に理解したりするのが簡単になります。
文字列を見つけます(スタックオーバーフローの色付けは正確には役に立ちませんが、VSではこれはより明白です):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
\u00ad
。
ここの誰もがいくつかの良い理論的な説明を与えました。私にも同様の疑いがありました。だから私はそれに基本的なコーディングを試みました。そして、私は違いを見つけました。ここに違いがあります。
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」は何らかの値が含まれていることを意味しますが、空です。
""
対についてであることに注意してくださいstring.Empty
。文字列が空であるかどうかを確認しようとしたときにのみ、null
言及されていました。
string.Empty
、それをのreadonly
代わりに宣言する理由は何でしたかconst
。