请查看以下代码:
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();
}
}
我希望这段代码崩溃,但事实并非如此。
为什么?
答案 0 :(得分:6)
这不是参考工作的方式。
Child child1 = new Child();
为新的Child
对象
Child child2 = child1;
创建另一个引用,该引用指向child1
所做的同一个对象
child1 = null;
将child1
引用设置为null
(它不再指向任何内容)。它不会更改它指向的对象,也不会影响child2
。 child2
仍然指向它之前所做的相同对象。
答案 1 :(得分:4)
不,您只是将child1变量中包含的参考值设置为空值 第二个对象实例仍包含原始参考值,仍然有效
以非常简单的方式,当你写
Child child1 = new Child();
在内存中创建child1
实例,并返回对它的引用,其值可以表示为值1000
。该值(引用)被分配给child1变量
Child child2 = child1;
您将相同的参考值1000
分配给第二个变量
child1 = null;
您将变量child1设置为零(或者null的实现者将null确定为null),但chidl2仍包含引用值1000.
仍然对正确创建原始对象的内存区域进行有效引用会阻止垃圾收集器从内存中删除该对象,您仍然可以安全地使用第二个变量
答案 2 :(得分:1)
与值类型变量不同,引用变量仅指向对象实例。您可以将多个变量指向同一个对象;将其中一个设置为null
并不会使对象本身不可用。就好像你说的那样#34; 现在它不再指向任何地方"。因此,它不会影响实例,更不用说仍然指向它的其他变量。
在您的代码中,您所做的是将child1
变量设置为null
,而child2
仍然指向您的实例。因此,代码完全有效并且不会崩溃。我理解它可能会让人感到困惑,因为field
属性在<{1}}和child1
上进行了更改,但是当你意识到它们都指向它时它确实有意义同样的例子。在这一点上,真正受到影响的不是child2
或child1
自己; child2
实例的field
成员都指的是那个。
当您的对象实例不存在其他指针时,垃圾收集器最终会从内存中清除它。但是,只要有东西指向它并且指针仍然在范围内,实例就不会去任何地方。
答案 3 :(得分:1)
是的,当您将对象分配给同一个类的另一个对象时,内存地址或引用是相同的。
但是当你child1=null;
时,child2
仍然引用它在初始化期间引用的同一个对象。
答案 4 :(得分:1)
首先创建一个子对象并将其分配给变量child1
Child child1 = new Child();
所以你可以认为它看起来像这样,child1
指向一个Child
对象的实例
child1 ----> { Child object }
然后你这样做:
Child child2 = child1;
这会复制引用,所以现在两个变量都指向同一个对象:
child1 ----> { Child object }
child2 ------------^
然后你这样做:
child1 = null;
这将从变量child1
中删除对Child
对象实例的引用。这里重要的一点是Child
对象本身不受此影响:
child1 { Child object }
child2 ------------^
因为child2
有一个参考的副本,它也不会受到影响,仍然指向您在开始时创建的Child
实例。