私がする時:
var foo = new Customer("Peter");
var sth = foo;
var foo2 = foo;
その後:
foo = new Customer("Dave");
のみfoo
が更新され、その他は「Peter」のままです。
しかし、私がするとき:
foo.Name = "Dave";
その後、すべてのオブジェクトが更新されます。どうしてこれなの?
ここでは、新しい顧客オブジェクトを foo に割り当てます。これらの 3 行は、foo、sth、および foo2 が Customer(Peter) を指していることを意味します。
var foo = new Customer("Peter");
var sth = foo;
var foo2 = foo;
しかし、ここでは、foo が別の顧客 (Dave) を指す必要があると言っています。他の「ポインター」は、Dave とは関係がないため変更されません。
foo = new Customer("Dave");
しかし、ここでは、Peter オブジェクトの Name プロパティを Dave に変更する必要があると言っています。foo を使用して実際のオブジェクトを取得し、オブジェクト自体の何かを変更しています。
foo.Name = "Dave";
sth と foo2 は、変更したオブジェクトをまだ指しています。彼らの参照は変更されませんでした。オブジェクト自体に内部変更がありました。sth と foo2 はそれを気にしません。彼らの唯一の仕事は、言われたことを指し示すことです。
この種の参照リンケージが本当に必要な場合 (非常に奇妙なケースですが)、次のような新しいクラスを作成できます。
public class CustomerRef
{
public Customer Obj { get; set; }
}
したがって、サンプル コードは次のようになります。
var foo = new CustomerRef(new Customer("Peter"));
var sth = foo;
var foo2 = foo;
その後
foo.Obj = new Customer("Dave");
すべての変数が新しいオブジェクトを参照し続けます。名前を変更したい場合は、次のようにします。
foo.Obj.Name = "Dave";
参照型になると、変数 (この例では foo) は参照のみを格納します。変数に新しい値を割り当てると、以前に参照したオブジェクトではなく、この変数のみが変更されます。
class Customer
{
public Customer(string name)
{
Name = name;
}
public string Name { get; set; }
public static Customer Current { get; set; }
}
期待される動作は、上記のコードで実行できます。Customer.Current を何らかの値に設定すると、Customer.Current を要求するすべてのコードは以前に設定された Customer を取得します。ただし、静的変数は通常、適切な設計選択ではなく、一連の問題 (テスト容易性、スレッドの問題など) が伴います。
参照は、ヒープ内のオブジェクトの単なるアドレスです (クラスは参照型です)。これを行うとどうなるか見てみましょう:
var foo = new Customer("Peter");
var sth = foo;
var foo2 = foo;
ヒープが米国であると想像してください。新しい顧客 Peter を作成すると、彼の住所は 33132 Miami Florida のようになります。アドレス帳のレコードなどの変数を検討してください。ピーターをいくつかの変数に割り当てると、実際にはピーターの体ではなく、ピーターのアドレスのみが保存されます(アドレス帳に人の体を保持するのは少し奇妙です)。あなたの例では、アドレス帳に 3 行あります。
var foo = [33132 Miami Florida] // Peter's address
var sth = [33132 Miami Florida] // copy address from foo record
var foo2 = [33132 Miami Florida]
次に、New Your に住む新しい顧客 Dave を作成します。
foo = new Customer("Dave");
foo
アドレス帳にオンラインで書かれたものを消去します。そこにデイブの住所を書き留めます。
var foo = [10012 New York, NY] // this is address of Dave!
var sth = [33132 Miami Florida] // other records in book has not changed
var foo2 = [33132 Miami Florida]
しかし、オブジェクトのアドレスを使用して彼にメッセージを送信する場合、これは別の話です。
foo.Name = "Dave";
これにより、マイアミに住む Peter に、名前を Dave に変更する必要があるというメッセージが送信されます。ピーターの住所は変更されていません。したがって、他のレコードにもピーターの住所が含まれています。変わったのはピーター!そして、ピーターは1人だけです。あなたは彼の住所をいくつかの記録で保持しているだけです。
記録からピーターの住所を取得sth
し、「ねえ、住所 33132 マイアミ フロリダの誰か、あなたの名前は?」というメッセージを彼に送信すると、ピーターはあなたに彼の新しい名前を送信します。
string name = sth.Name;
ところで、ガベージコレクターは、アドレス帳にアドレスが存在する人々だけを殺すわけではありません。
参照は、値がオブジェクトへの参照である変数です。別のオブジェクトを指すように参照を変更すると、値は新しい参照になります。したがって、前のオブジェクトへの参照は変更されません。