1

当我做:

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

进而:

foo = new Customer("Dave");

onlyfoo已更新,其他仍将是“Peter”。

但是当我这样做时:

foo.Name = "Dave";

然后更新所有对象。为什么是这样?

4

5 回答 5

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。但是,静态变量通常不是很好的设计选择,并且会带来一系列问题(可测试性、线程问题等)。

于 2012-05-03T11:38:59.917 回答
1

在这里,您将一个新的客户对象分配给 foo。这三行表示 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 仍然指向您更改的对象。他们的参考没有改变;对象本身发生了内部变化。某事和 foo2 不在乎,他们唯一的工作就是指出他们被告知的任何内容。

于 2012-05-03T11:49:08.873 回答
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"; 
于 2012-05-03T12:03:42.440 回答
0

引用是一个变量,其值是对对象的引用。当您将引用更改为指向不同的对象时,该值是一个新的引用。因此,对前一个对象的引用保持不变。

于 2012-05-03T11:40:23.463 回答
0

引用只是堆中对象的地址(类是引用类型)。让我们看看当你这样做时会发生什么:

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

想象堆是美国。当您创建新客户 Peter 时,他有一些地址,例如 33132 Miami Florida。考虑变量,例如地址簿中的记录。当您将 Peter 分配给某个变量时,它实际上只存储了 Peter 的地址,而不是 Peter 的身体(将人员的身体保存在地址簿中有点奇怪)。在您的示例中,地址簿中有三行:

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

然后您创建新客户 Dave,该客户居住在 New Your 中:

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

这向住在迈阿密的彼得发送了一条消息,他应该将自己的名字改为戴夫。彼得的地址没有改变。所以其他记录也包含彼得的地址。改变的是彼得!而且只有一个彼得。您只需将他的地址保存在几份记录中。

如果您从sth记录中获取 Peter 的地址,并向他发送消息“嘿,有人在地址 33132 Miami Florida,你叫什么名字?”,那么 Peter 将向您发送他的新名字:

string name = sth.Name;

顺便说一句,垃圾收集器不会只杀死地址簿中存在的那些人。

于 2012-05-03T12:10:15.780 回答