文字列内の個々の文字に割り当てようとするとs[i] = c、コンパイラ エラーが発生します。
string s = "bcc";
s[0] = 'a'; // shows compile time error - indexer cannot be assigned - it's readonly
ただし、これは機能します:
s.ToCharArray()[0] = 'a';
accまた、文字列を次のように完全に割り当てることもできます。
s = "acc"
これ:
s="acc"
...変数の値を変更して、別の文字列を参照しています。これが許可されている場合:
s[0] = 'a';
それは変数の値を変更するのではなく、s参照する文字列の内容を変更する必要があります。文字列は .NET では不変であるため、許可されていません。
変数の値を変更することと、変数が参照するオブジェクト内のデータを変更することを区別することが重要です。
の内容を変更しても、どちらs.ToCharArray()の文字列にも何も起こりません。文字列内のデータのコピーである新しく作成された配列を変更するだけです。s
MSDNから:
文字列は不変です。文字列オブジェクトの内容は、オブジェクトが作成された後に変更することはできませんが、構文上は変更できるかのように見えます。たとえば、このコードを記述すると、コンパイラは実際には、新しい文字列を保持する新しい文字列オブジェクトを作成し、その新しいオブジェクトが b に割り当てられます。文字列 "h" はガベージ コレクションの対象になります。
s.ToCharArray()文字列の内容を配列にコピーしています。ただし、この文字列参照の最初の文字を変更することはできません。この文字列自体は変更されません。
文字列は、.NET ではコピー オン ライト (より正確には、文字列プールに基づく) および参照型として実装されます。あなたがしようとしているのは、文字列を構成する基になる char[] を取得し、それを変更することです。ただし、stringコピーオンライトとして実装されているため、それが成功した場合、1 つの文字列だけでなくすべての文字列を変更することになります。
たとえば、コードが文字列を変更すると、次のようになります (誤った仮定を説明するため):
string s = "foo"; // create instance with foo
string t = s; // copy reference, contents aren't changed
char[] ch = s.ToCharArray(); // attempt to access underlying contents
ch[0] = 'b'; // attempts to change the underlying contents
Console.WriteLine(t); // 'boo'?
試してみると、基になるコンテンツがそのまま残るため、t は 'foo' になります。ToCharArray は基になるコンテンツのコピーを作成し、基になるコンテンツを保護して、同じ文字列オブジェクトへの他の参照が影響を受けないようにします。
これは、このようなコードが悪い習慣である理由でもあります:
string s = "";
for (int i=0; i<10000; ++i)
{
// makes a new instance of the string, copies the contents
// and appends a single char... as you can see 10K times...
s = s + "a";
}
これが、文字列が不変として実装されている理由です。文字列への参照が異なるコンテンツを取得しないように保護するためです。
文字列プールの動作については、こちらも参照してください。
この答えは、問題について説明するためではなく、インデックスのベースreadonlyを変更したい場合です。char
var s = "bcc".ToCharArray();
s[0] = 'a';
Console.WriteLine(s[0].ToString());
s[0]と直接比較することはできませんs.ToCharArray()[0]。
s[0]String オブジェクトの最初の要素にアクセスしようとしています。
s.ToCharArray()c[N] などの文字の配列を返します。これで0番目の要素にアクセスできます。
そして、s = "pqr";オブジェクト s が指している文字列値を変更しています。