空文字を記述するのに、String.Empty と "" のどちらの記述の方が良いかという話。
空の文字列
String.Empty
今日から・・・。
以前も書いたけど、もう一回。C# の限定で話をする(他の言語はまた違う都合があるかもしれない)。
次のように書いたらメモリのイメージは以下のようになる。
string s1 = "";
string s2 = "";
よく目にするのが「"" と書くと、毎回インスタンスができるから無駄」という誤解。「"" と書いても、毎回インスタンス化されない」のが正しい理解だ。文字列がこのようになるのはインターンプールがあるからである。非常に長い文字列をインターン化すると、プールから探し出すのに時間がかかるため、全ての文字列がインターン化されるとは限らないが、"" はとても短いため 100% インターン化される(はず)。
更に、次のように書いた場合のメモリのイメージも示す。
string s1 = String.Empty;
string s2 = String.Empty;
string s3 = "";
string s4 = "";
但し、これは .NET Framework 2.0 以降の話。.NET Framework 1.x では、String.Empty も "" も同一のインスタンスだった。
上記のメモリイメージ図にアセンブリも加えてみる。
メモリの概念にアセンブリもクソもないのだが、mscorlib.dll はネイティブイメージ化されているため、固定部分はネイティブ DLL ファイルがそのまま仮想メモリ空間にマッピングされる(要するにメモリマップドファイル)。文字列は、適切な属性などをつけたらネイティブイメージのものが使われるのは前回述べた通り。
マイコード中に "" を一切書かないならば、メモリ効率という点では、String.Empty だけを使う方に軍配が上がる。
string s1 = String.Empty;
string s2 = String.Empty;
string s3 = String.Empty;
string s4 = String.Empty;
しかし、"" というインスタンスがたった一個できるかどうかの違いなんて些細過ぎる。マウスを 1cm 動かす方がよっぽど負荷がかかるだろう(多分)。
それよりも、String.Empty と "" にはもっと大きな違いがある。それは、IL を見れば一目瞭然。
string s1 = String.Empty;
ldsfld string [mscorlib]System.String::Empty
string s1 = "";
ldstr ""
String.Empty は文字列ではなく「フィールド」なのである。フィールドであるため、String.Empty をロードして参照を辿っていかなければならない。"" の方は単純にメタデータのリテラル文字を突っ込んで終わり。どちらの方が速いのか、公式の資料がないので(あるかもしれないけど知らない)正確には分からないが、後者の方が断然速いはず。(※1)。
まとめると、「パフォーマンスが良いから String.Empty を使う」という主張はまるっきり逆で、「パフォーマンスを気にするなら "" を使う」が正解。
可読性を気にするならお好きな方を使えば良い。私は無意味にコードを長くしたくないので "" しか使いたくない。
※1 コンパイル時や JIT 時に最適化されたら話は変わる。