将一个对象分配给同一类的另一个对象

7
请看下面的代码:
class Parent{}

class Child : Parent
{
    public int field 
    {
        get; 
        set;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Child child1 = new Child();
        Child child2 = child1;              //same memory address?

        child1.field = 12;
        child2.field = 14;

        Console.WriteLine(child1.field);    //14, as expected

        child1 = null;
        Console.WriteLine(child2.field);    //expected to crush: 'child1' is null so expected 'child2' to also be null

        Console.ReadLine();
    }
}

我以为这段代码会崩溃,但它却没有。

为什么呢?


3
如果在child2中仍有一个引用,那么这个对象仍然存在! - Fals
将变量设置为 null 不会销毁它所指向的对象。只有当没有更多的引用并且垃圾回收运行时,对象才会被销毁(垃圾回收)。 - Matt Burland
我猜你想用 child1 = null; 实际上是想用 child1.Dispose(); 吧? - Batu.Khan
5个回答

13

那不是引用的工作方式。

Child child1 = new Child();

创建对新Child对象的引用

Child child2 = child1;  

创建另一个引用,指向与child1相同的对象

child1 = null;

child1引用设置为null(它不再指向任何东西)。它不会更改被指向的对象,也不会影响child2child2仍然指向之前的同一对象。


4
不,你只是将child1变量中包含的引用值设置为null。
第二个对象实例仍然包含原始的引用值并且仍然可以使用。
简化来说,当你写下以下代码时:
Child child1 = new Child();

在内存中创建了child1实例,并返回一个引用其值我们可以表示为1000的对象。这个值(引用)被分配给了child1变量。

Child child2 = child1;              

您将同样的引用值1000分配给第二个变量。

child1 = null;

你将变量child1设置为零(或者是实现null的值),但是child2仍然包含引用值1000。
仍然拥有原始对象所在内存区域的有效引用会正确阻止垃圾回收器从内存中移除该对象,你仍然可以安全地使用第二个变量。

4

首先创建一个子对象并将其分配给变量child1

Child child1 = new Child();

因此,您可以将其视为这样,child1指向一个Child对象的实例

child1 ---->  { Child object }

然后你这样做:
Child child2 = child1;

这会复制引用(reference),现在两个变量都指向同一个对象:
child1 ---->  { Child object }
child2 ------------^

然后你这样做:
child1 = null;

这将从变量child1中删除对Child对象实例的引用。 这里的重要点是Child对象本身不受影响:

child1        { Child object }
child2 ------------^

因此,由于child2拥有引用的副本,它也不受影响,并且仍然指向你在开始时创建的Child实例。


1
与值类型变量不同,引用变量仅是指向对象实例的指针。您可以有多个变量指向同一对象;将其中一个设置为null并不会使对象本身不可用。这就好像你在说“现在这个不再指向任何地方了”。因此,它不会影响实例,更不用说仍然指向它的其他变量了。
在您的代码中,您所做的是将child1变量设置为null,而child2仍然指向您的实例。因此,代码是完全有效的,不会崩溃。我理解这可能会令人困惑,因为field属性确实在child1和child2上都发生了改变,但当您意识到它们都指向同一个实例时,这确实是有道理的。此时真正受影响的不是child1或child2本身,而是它们都指向的Child实例的field成员。
当没有其他指针指向您的对象实例时,垃圾收集器最终会从内存中清除它。但只要有东西指向它并且该指针在范围内仍然存在,该实例就不会消失。

1
当您将一个对象分配给同一类的另一个对象时,内存地址或引用是相同的。但是,当您执行child1=null;时,child2仍然引用在初始化期间所引用的相同对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接