a
が指している値を変更しなかったため、参照自体が変更されました。例えば、Cの場合と同じです。a = "Hi"
が変更されているとは思わないでください。*a
。
実際、安全でないコードの外には、既存の文字列を変更する方法はありません。 .NETの文字列は不変です。新しい文字列を作成するか参照を変更するだけです。つまり、string
は他の不変のデータ型と同様に値の意味を持ちます。これは設計上の選択肢でした。文字列は難しく、これではずっと簡単になりました。
代入演算子はC#ではオーバーライドできません。これは常に「識別子に値を代入する」ことを意味します。 string
の場合、値は文字列自体ではなく、文字列に対する参照です。しかし、ある地方の参照を変更しても他の地方の参照は変更されません。それはどうですか?ポインタへのポインタではありません。
のは、参照型と値型の違いのより良いイラストを作ってみましょう:
void Main()
{
A a = default(A), b = default(A);
a = b = new A { Number = 42 };
a.Number = 10;
Console.WriteLine(a); // 42
Console.WriteLine(b); // 10
}
public struct A
{
public int Number;
}
さて、Aが値型であり、私たちはa
にb
を割り当てるとき、私たちは実際にコピーを作成します。 2人の地元の人は同じオブジェクトを指していません。 a.Number
が10に変更されたときあなたはpublic class A
ではなく、割り当ては参照のみの値を変更すると言って宣言を変更するのであれば、b.Number
が、しかし42
まま - 言い換えれば、A
のインスタンスは1つだけ存在します。次に、a.Number = 10
は実際にはb.Number
に変更されます.2つはメモリ内の同じ場所です。
これをCと比較すると、値型のローカルが値そのものであるかのようになりますが、参照型のローカルはのポインタの値になります。したがって、次のようなものがあります。
// Value-type
A a, b;
b.Number = 42;
a = b;
a.Number = 10; // Only the value in a is changed
// Reference-type
A *a, *b;
a = b = new A(42);
a->Number = 10; // Both locals point to the changed value
これはC++の参照がどのように機能するかとはかなり異なります。これらはC#ではメソッド引数に限定されています。したがって、たとえば、C#でのスワップ方法は次のようになります。
void Main()
{
int a = 42, b = 10;
Swap(ref a, ref b);
Console.WriteLine(a); // 10
Console.WriteLine(b); // 42
}
public void Swap(ref int a, ref int b)
{
int x = 0;
SwapI(ref a, ref b, ref x);
}
// No ref locals, so we need a helper method
private void SwapI(ref int a, ref int b, ref int x)
{
x = a;
a = b;
b = x;
}
我々は切り替えている引数はref
なので、彼らは関係なく、常に型が値型または参照型であるかどうかの、参照セマンティクスを持っています。
あなたの理解は間違っていると思います。 'a'と' b'はそれ自身の変数であり、したがってそれら自身の値です。あなたが考えているのは参照型です。これらは値型です。また、文字列は不変であるため、変更すると文字列全体が変更されます。 –
あなたの質問は値型と参照型とは関係ありません。 'a'と' b'は異なる変数であるため、一方に割り当てることは他方には影響しません。 – Lee
@RichardBarkerあなたが間違っていると、参照型と値型の両方でこの動作が発生します。また、文字列は値型ではありません。最後に、あなたが不変について話したことは少しあいまいです。不変なことは変更を加えることで新しいオブジェクトを返しますが、元のものは変更されていないことを意味します。新しいオブジェクトを使用するには変数を新しいオブジェクトで上書きする必要がありますオブジェクト。 –