C# で型の変数を作成したい場合は、string
次を使用できます。
string str="samplestring"; // this will allocate the space to hold the string
C# では、string
はクラス型であるため、オブジェクトを作成する場合は通常、new
キーワードを使用する必要があります。new
では、 orなしで割り当てはどのように行われるのconstructors
でしょうか?
C# で型の変数を作成したい場合は、string
次を使用できます。
string str="samplestring"; // this will allocate the space to hold the string
C# では、string
はクラス型であるため、オブジェクトを作成する場合は通常、new
キーワードを使用する必要があります。new
では、 orなしで割り当てはどのように行われるのconstructors
でしょうか?
あなたが書くとき
string str="samplestring";
コンパイラは2つの命令を生成します。
ldstr
メタデータから文字列リテラルを取得します。必要な量のメモリを割り当てます。新しいString
オブジェクトを作成し、そのオブジェクトへの参照をスタックにプッシュします。stloc
(またはその短縮形の1つ、たとえばstloc.0
)は、その参照をローカル変数に格納しますstr
。ldstr
これにより、文字のシーケンスごとに1回だけメモリが割り当てられることに注意してください。
したがって、以下の例では、両方の変数がメモリ内の同じオブジェクトを指します。
// CLR will allocate memory and create a new String object
// from the string literal stored in the metadata
string a = "abc";
// CLR won't create a new String object. Instead, it will look up for an existing
// reference pointing to the String object created from "abc" literal
string b = "abc";
このプロセスは、文字列インターンとして知られています。
また、ご存知のように、.NETでは文字列は不変です。したがって、String
オブジェクトの作成後にオブジェクトの内容を変更することはできません。つまり、文字列を連結するたびに、CLRは新しいString
オブジェクトを作成します。
たとえば、次のコード行です。
string a = "abc";
string b = a + "xyz";
次のILにコンパイルされます(もちろん、正確ではありません)。
ldstr
メモリを割り当て、リテラルから新しいString
オブジェクトを作成します"abc"
stloc
そのオブジェクトへの参照をローカル変数に格納しますa
ldloc
その参照をスタックにプッシュしますldstr
メモリを割り当て、リテラルから新しいString
オブジェクトを作成します"xyz"
call
System.String::Concat
スタック上のこれらのString
オブジェクトでを呼び出しますSystem.String::Concat
、数十のIL命令と内部呼び出しに分解されます。つまり、両方の文字列の長さをチェックし、連結結果を格納するために必要な量のメモリを割り当ててから、それらの文字列を新しく割り当てられたメモリにコピーします。stloc
新しく作成された文字列への参照をローカル変数に格納しますb
これは、文字列リテラルを許可することでショートカットを提供する C# コンパイラにすぎません。
必要に応じて、任意の数の異なるコンストラクターで文字列をインスタンス化できます。例えば:
char[] chars = { 'w', 'o', 'r', 'd' };
string myStr = new String(chars);
MS のドキュメントによると、デフォルトの文字列コンストラクターを使用するために新しいコマンドを使用する必要はありません。
ただし、これは機能します。
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);
文字列は実際には参照型です。変数は、メモリ内の値への参照を保持します。したがって、値ではなく参照をオブジェクトに割り当てるだけです。Pluralsight のこのビデオをご覧になることをお勧めします (14 日間の無料試用版を入手できます)。
免責事項: 私は Pluralsight とは一切関係ありません。私はサブスクライバーで、向こうのビデオが大好きです
.net ではすべてがオブジェクトですが、インスタンス化を必要としないプリミティブ型 (int、bool など) がまだあります。ここでわかるように、文字列は、最大 2GB まで拡張できるベクトル/配列構造を指す 4 バイトのアドレス ref です。文字列は変更できない型であるため、文字列を変更するときは既存の変数を編集するのではなく、リテラル値に新しいメモリを割り当ててから、文字列ポインタを新しいメモリ構造を指すように変更します。それが役立つことを願っています
内部的にリテラルを使用して文字列を作成すると、アセンブリが NoStringInterning フラグでマークされているかどうかに応じて、次のようになります。
String str = new String("samplestring");
// or with NoStringInterning
String str = String.Intern("samplestring");
あなたがそのような何かを書くならば、Javaで:
String s1 = "abc";
String s2 = "abc";
メモリはいわゆる文字列プールの「abc」に割り当てられ、s1とs2の両方がそのメモリを参照します。そして、s1 == s2はtrueを返します( "=="は参照を比較します)。しかし、あなたが書く場合:
String s1 = new String("abc");
String s1 = new String("abc");
s1==s2はfalseを返します。C#でも同じだと思います。