2016-07-14 8 views
0

stringは参照型ですが、値型のように機能します。文字列は値型のように機能します

string a,b; 
a=b="test"; //As i understood a and b have to point to the same location in the heap 

a="a"; 
Console.WriteLine("a: {0}, b: {1}",a,b); 

としては、印刷結果:、B:一方は参照型ルールに従って期待することができるようにaへの変更をbに反映されていない理由を説明テスト ください。

+1

あなたの理解は間違っていると思います。 'a'と' b'はそれ自身の変数であり、したがってそれら自身の値です。あなたが考えているのは参照型です。これらは値型です。また、文字列は不変であるため、変更すると文字列全体が変更されます。 –

+2

あなたの質問は値型と参照型とは関係ありません。 'a'と' b'は異なる変数であるため、一方に割り当てることは他方には影響しません。 – Lee

+3

@RichardBarkerあなたが間違っていると、参照型と値型の両方でこの動作が発生します。また、文字列は値型ではありません。最後に、あなたが不変について話したことは少しあいまいです。不変なことは変更を加えることで新しいオブジェクトを返しますが、元のものは変更されていないことを意味します。新しいオブジェクトを使用するには変数を新しいオブジェクトで上書きする必要がありますオブジェクト。 –

答えて

3

aのオブジェクトを変更していない場合は、変数aのみを変更しています。これは文字列では特別なものではなく、どのような型でもこれを行うことができ、全く同じ動作を得ることができます。

class Foo 
{ 
    private int _i; 

    public Foo(int i) 
    { 
     _i = i; 
    } 

    public override string ToString() 
    { 
     return _i.ToString(); 
    } 
} 

Foo a, b; 
a=b= new Foo(1); 

a=new Foo(2); 

Console.WriteLine("a: {0}, b: {1}",a,b); 

私は変数とその関連オブジェクト間の差のアナロジーで深さに行く、this questionに私の答えを参照してください。

1

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が値型であり、私たちはabを割り当てるとき、私たちは実際にコピーを作成します。 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なので、彼らは関係なく、常に型が値型または参照型であるかどうかの、参照セマンティクスを持っています。

0

//変数をインテリタイズしました。
文字列a、b;

// = "テスト"B = "テスト"
= B = "テスト"。 B

//今= ""はまだあり"テスト"
= "A";


bを「a」として表示するには、「a」と設定する必要があります。変数を設定する唯一の方法は、変数が左側にある宣言を作成することです。ですから、bを "a"と同じにするには、次のようなことをしなければなりません。
b = a;最後の行の後にだからあなたは3行で、次のようになります:

a = b = "test";
a = "a";
//改行
b = a;
Console.WriteLine( "a:{0}、b:{1}"、a、b)と入力します。
あなたはを取得します:a、b:a

関連する問題