2010-11-26 12 views
13

C#コンパイラまたは.NET CLRは文字列リテラル/定数の賢明なメモリ最適化を行いますか?私は "文字列の内部化"という概念について聞いたことがありますので、プログラム内の任意の2ビットのコードでは、 "これは文字列です"というのは実際には同じオブジェクトを参照していました(おそらく安全です。不変?)。私はGoogle上でそれに有用な参照を見つけることはできません...C#文字列リテラルはコンパイラによって最適化されますか?

これは間違って聞いたことがありますか?心配しないでください - 私はこの情報で私のコードの中で恐ろしいことをやっていません、ちょうどそれがどのようにカバーの下で動作するかの私の理解をより良くしたいです。

+0

関連するhttp://stackoverflow.com/q/372547/38206 –

答えて

17

編集:私は強く、以下の文は、すべてのC#コンパイラの実装のために真である疑いがある一方で、私は」実際に仕様で保証されているかどうかわかりません。仕様の2.4.4.5節では、同じ文字列インスタンスを参照するリテラルについて説明していますが、他の定数文字列式については言及していません。私は容疑者これは仕様の見落としです - 私はそれについてのマッズとエリックにメールします。


文字列リテラルだけではありません。任意の文字列定数です。だから、例えば、考えてみます。

public const string X = "X"; 
public const string Y = "Y"; 
public const string XY = "XY"; 

void Foo() 
{ 
    string z = X + Y; 
} 

をコンパイラはここ(z用)連結は2つの定数文字列の間にあり、その結果も一定の文字列であることを実現しています。したがって、初期値zは、同じ値のコンパイル時定数であるため、XYの値と同じ参照になります。

編集:MadsとEricからの返信は、Microsoft C#コンパイラの文字列定数と文字列リテラルは、通常は同じ方法で扱われますが、他の実装は異なる可能性があることを示しています。

+0

異なるアセンブリの2つの同一の文字列定数が同じオブジェクトを指していますか? /ジッターインターナル文字列リテラルですか? – CodesInChaos

+0

@CodeInChaos:私はそれが 'CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)'属性に依存すると信じています。私は確かに言いたい。 –

+0

こんにちは@JonSkeet、同じ内容のinterned文字列が常に同じ参照を持っているかどうかアドバイスをしてください?このような文字列の参照を比較するとtrueが返されますか? –

6

This articleは、文字列のインターナショナルをかなりうまく説明しています。見積もり:

.NETには「intern プール」の概念があります。これは基本的には 文字列のセットですが、同じ文字列を リテラルとして参照するたびに、 の文字列が参照されるようになります。 同じ文字列が参照されます。これはおそらく 言語に依存していますが、それは確かに C#とVB.NETで真です、そして、私は非常に 言語を見て驚いたでしょう は、ILが非常に簡単にするので、 するおそらく インターンリテラルに失敗するよりも簡単です)。同様にリテラル が自動的に抑留されていると、あなたは インターン文字列を手動 インターン方法ではなく、すでに IsInternedメソッドを使用して、プール内の同じ文字 配列とインターン 文字列があるかどうか 確認することができます。これはやや は、ブール値よりむしろ という文字列を直観的に返します。プール内の等しい文字列が の場合、その 文字列への参照が返されます。そうでない場合、nullは が返されます。同様に、インターン 文字列への参照を返します インターン方法 - のいずれかの文字列は、あなたは、プール、または 新しく作成されたインターン文字列、または プールですでにだった 等しい文字列にすでにだった場合に を可決しました。

+1

Sidenote:AppDomainのライブタイム中にインターナショナル文字列が解放されないため、interingを不適切に使用するとメモリリークが発生する可能性があります。 – CodesInChaos

7

はい、文字列リテラルを最適化します。あなたがそれを見ることができる一つの簡単な例:

string s1="A"; 
string s2="A"; 
object.ReferenceEquals(s1,s2); //true 
関連する問題