.NetでString.Emptyが定数ではなく読み取り専用になるのはなぜですか?誰かがその決定の背後にある理由が何であるかを知っているのかと思っています。
.NetでString.Emptyが定数ではなく読み取り専用になるのはなぜですか?誰かがその決定の背後にある理由が何であるかを知っているのかと思っています。
回答:
static readonly
代わりに使用される理由const
は、Microsoftが共有ソース共通言語インフラストラクチャ2.0リリースでここに示したように、アンマネージコードで使用するためです。確認するファイルはsscli20\clr\src\bcl\system\string.cs
です。
空の定数は、空の文字列値を保持します。コンパイラがこれをリテラルとしてマークしないように、Stringコンストラクタを呼び出す必要があります。
これをリテラルとしてマークすると、ネイティブからアクセスできるフィールドとして表示されなくなります。
CodeProjectのこの便利な記事からこの情報を見つけました。
String.Empty
その理由だけでもう使わないことを真剣に考えています。
ここには多くの混乱と悪い反応があると思います。
まず、const
フィールドはstatic
メンバーです(インスタンスメンバーではありません)。
C#言語仕様のセクション10.4定数を確認してください。
定数は静的メンバーと見なされますが、定数宣言は静的修飾子を必要とせず、許可もしません。
public const
メンバーが静的である場合、定数が新しいオブジェクトを作成するとは考えられません。
このため、次のコード行は、新しいオブジェクトの作成に関してまったく同じことを行います。
public static readonly string Empty = "";
public const string Empty = "";
以下は、2つの違いを説明するMicrosoftからのメモです。
readonlyキーワードは、constキーワードとは異なります。constフィールドは、フィールドの宣言時にのみ初期化できます。読み取り専用フィールドは、宣言時またはコンストラクターで初期化できます。したがって、読み取り専用フィールドは、使用するコンストラクターに応じて異なる値を持つことができます。また、constフィールドはコンパイル時の定数ですが、readonlyフィールドはランタイム定数に使用できます...
だから私はここでもっともらしい答えはジェフ・イェーツのものだと思う。
const string
してstatic readonly string
同じことを行います。静的な読み取り専用の値が参照されるのに対し、リンクされたコードではconst値が置き換えられます。const
ライブラリーBで使用されるライブラリーA がある場合、ライブラリーBはそのconst
変数へのすべての参照をリテラル値で置き換えます。その変数がstatic readonly
代わりにあった場合、それは参照され、その値は実行時に決定されます。
String.Empty read only instead of a constant?
文字列を定数にすると、コンパイラは実際の文字列に置き換えます。コード全体に同じ文字列を入力します。コードを実行すると、別のメモリからその文字列を何度も読み取る必要があります。データ。
文字列を1つの場所でのみ読み取りのString.Empty
ままにすると、プログラムは同じ文字列を1つの場所でのみ保持して読み取り、または参照する-メモリ内のデータを最小限に抑えます。
また、あなたはconstのようString.Emptyのを使用して、任意のDLLをコンパイルした場合、いかなる理由でString.Emptyを変更し、次にコンパイルしたDLLは、任意のより多くの同じように動作しませんのでcost
に内部のコードを作成し、実際に文字列のコピーを保持しますすべての呼び出しで。
たとえば、次のコードを参照してください。
public class OneName
{
const string cConst = "constant string";
static string cStatic = "static string";
readonly string cReadOnly = "read only string";
protected void Fun()
{
string cAddThemAll ;
cAddThemAll = cConst;
cAddThemAll = cStatic ;
cAddThemAll = cReadOnly;
}
}
コンパイラーは次のようになります。
public class OneName
{
// note that the const exist also here !
private const string cConst = "constant string";
private readonly string cReadOnly;
private static string cStatic;
static OneName()
{
cStatic = "static string";
}
public OneName()
{
this.cReadOnly = "read only string";
}
protected void Fun()
{
string cAddThemAll ;
// look here, will replace the const string everywhere is finds it.
cAddThemAll = "constant string";
cAddThemAll = cStatic;
// but the read only will only get it from "one place".
cAddThemAll = this.cReadOnly;
}
}
とアセンブリ呼び出し
cAddThemAll = cConst;
0000003e mov eax,dword ptr ds:[09379C0Ch]
00000044 mov dword ptr [ebp-44h],eax
cAddThemAll = cStatic ;
00000047 mov eax,dword ptr ds:[094E8C44h]
0000004c mov dword ptr [ebp-44h],eax
cAddThemAll = cReadOnly;
0000004f mov eax,dword ptr [ebp-3Ch]
00000052 mov eax,dword ptr [eax+0000017Ch]
00000058 mov dword ptr [ebp-44h],eax
編集:タイプミスを修正
この答えは歴史的な目的のために存在します。
もともと:
そのためString
、クラスであるため、一定とすることができません。
拡張ディスカッション:
この答えを吟味することで多くの有用なダイアログが打ち出されました、そしてそれを削除するのではなく、このコンテンツは直接再現されます:
.NETでは、(Javaとは異なり)文字列と文字列はまったく同じです。そして、はい、.NETで文字列リテラル定数を使用できます– DrJokepu Feb 3 '09 at 16:57
クラスは定数を持つことができないと言っていますか?– StingyJack、2009年2月3日16:58
はい、オブジェクトは読み取り専用を使用する必要があります。構造体だけが定数を実行できます。コンパイラの
string
代わりに使用String
すると、constが読み取り専用に変わります。Cプログラマを満足させるために必要なことはすべて。– Garry Shutler、2009年2月3日16:59tvanfossonは、もう少し詳細に説明しました。「Xを定数にすることはできません。Yを含むクラスはクラスであるためです」コンテキストに依存していません;)– Leonidas Feb 3 '09 at 17:01
string.Emptyは、Stringクラス自体ではなく、Stringクラスのインスタンス、つまり空の文字列を返す静的プロパティです。– tvanfosson 2009年2月3日17:01
空は、Stringクラスの読み取り専用インスタンスです(プロパティではありません)。– senfo 2009年2月3日17:02
頭が痛い。私はまだ正しいと思いますが、今は確信が持てません。今夜必要な研究!– Garry Shutler、2009年2月3日17:07
空の文字列は文字列クラスのインスタンスです。空は、Stringクラスの静的フィールド(プロパティではなく、修正済みです)です。基本的に、ポインターとそれが指すものの違い。読み取り専用でなければ、Emptyフィールドが参照するインスタンスを変更できます。– tvanfosson 2009年2月3日17:07
ギャリー、調査をする必要はありません。それについて考えてください。文字列はクラスです。空は文字列のインスタンスです。– senfo 2009年2月3日17:12
まったく理解できないことがあるのですが、いったいどのようにしてStringクラスの静的コンストラクターがStringクラスのインスタンスを作成できるのでしょうか。それはある種の「鶏または卵」のシナリオではないでしょうか?– DrJokepu 2009年2月3日17:12 5
この答えは、System.String以外のほぼすべてのクラスに当てはまります。.NETは文字列に対して多くの特別なパフォーマンスケースを実行します。その1つは、文字列定数を使用できることです。試してみてください。この場合、Jeff Yatesが正解です。– Joel Mueller、2009年2月3日19:25
§7.18で説明されているように、定数式はコンパイル時に完全に評価できる式です。string以外の参照型のnull以外の値を作成する唯一の方法は新しい演算子を適用することであり、定数式では新しい演算子を使用できないため、参照型の定数に使用できる唯一の値文字列以外はnullです。前の2つのコメントはC#言語仕様から直接取られたものであり、Joel Muellerが述べたことを繰り返します。– senfo 2月4日09日15:05 5