2012-05-03 8 views
1

當我這樣做:爲什麼它是一個對象設置爲不同的實例時,只有本地參考更新

var foo = new Customer("Peter"); 
var sth = foo; 
var foo2 = foo; 

然後:

foo = new Customer("Dave"); 

foo更新和其他人仍然是「彼得」。

但是當我做:

foo.Name = "Dave"; 

那麼所有的對象都更新。爲什麼是這樣?

+0

你是否起訴foo.Name更改sth.Name和foo2.Name?它應該只改變foo.Name –

+0

最初foo,sth和foo2都指向同一個對象,因此該對象的Name屬性對於所有三個引用都會顯示更改。一旦將不同的對象(「Dave」)分配給foo,則名稱更改不會再影響它。 –

回答

1

當涉及引用類型時,變量(在您的示例中爲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。但是,靜態變量通常不是很好的設計選擇,並伴隨着它們的一系列問題(可測試性,線程問題等)。

+0

任何方式來改變所有的引用沒有太多麻煩? – user1151923

+0

可能有很多變量引用同一個對象。如果使用其中一個引用更改對象,則可以從指向該對象的每個變量中看到更改。 – empi

+0

是的,我明白,但我想切換一個完全不同的實例的對象,以便所有的引用得到更新,並'看'新的對象 – user1151923

0

引用是一個變量,其值是對該對象的引用。當您將參考更改爲指向不同的對象時,該值是新的參考。因此,對前一個對象的引用保持不變。

1

在此處爲foo分配新客戶對象。這三行意味着富,某事,和foo2的指向客戶(彼得):

var foo = new Customer("Peter"); 
var sth = foo; 
var foo2 = foo; 

但在這裏,你是說,FOO應指向另一個客戶(戴維)。其他的「指針」不改變,因爲他們什麼都沒有做與戴夫:

foo = new Customer("Dave"); 

但在這裏,你是說,在彼得對象的名稱屬性應該改變戴夫。您正在使用FOO獲得實際的對象,然後改變物體本身的東西:

foo.Name = "Dave"; 

......而foo2的仍然指向你改變的對象。他們的引用沒有改變;對象本身發生了內部變化。某事和富二不關心這一點,他們唯一的工作就是指向他們所說的任何事情。

1

如果你真的想這樣的基準連桿機構(很奇怪的情況,順便說一句),你可以創建一個新的類,如:

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"; 
0

參考僅僅是對象在堆(類是引用類型)的地址。讓我們看看當你這樣做時會發生什麼:

var foo = new Customer("Peter"); 
var sth = foo; 
var foo2 = foo; 

想象一下,堆是美國。當你創造新的客戶彼得時,他有一些像佛羅里達州邁阿密33132的地址。考慮地址簿中的記錄等變量。當你將Peter分配給某個變量時,它實際上只存儲彼得的地址,而不是彼得的身體(它在通訊簿中保持人體的奇怪)。在您的例子有三個行地址簿:

var foo = [33132 Miami Florida] // Peter's address 
var sth = [33132 Miami Florida] // copy address from foo record 
var foo2 = [33132 Miami Florida] 

然後創建新的客戶戴夫其住在新的你:

foo = new Customer("Dave"); 

您刪除什麼是你的地址簿寫上線foo。並放下Dave的地址:

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"; 

這會發送消息給彼得,他住在邁阿密,他應該改名爲戴夫。彼得的地址沒有改變。所以其他記錄也持有彼得的地址。改變的是彼得!而且那裏只有一個彼得。你只是在幾個記錄中保存他的地址。

如果你從sth記錄彼得的地址,並給他發信息「嘿,有人在地址33132佛羅里達州邁阿密,你叫什麼名字?」,然後彼得會送你他的新名字:

string name = sth.Name; 

順便說一句垃圾收集器不殺死只有那些人,哪個地址存在於地址簿中。

相關問題