我发现了以下我很难理解的行为。
我假设你可以将对象A的属性设置为对象B,操纵对象B,并且更改将被带到对象A的属性(因为它是同一个对象)。我期待这个单元测试通过但是在将B设置为null时它在最后一行失败。为什么呢?
[TestMethod]
public void TestObject()
{
Child child = new Child();
var parent = new Parent(child);
child.Name = "John";
Assert.AreEqual(parent.Child.Name, "John");
child = null;
Assert.IsNull(parent.Child);
}
public class Child
{
public string Name { get; set; }
}
public class Parent
{
public Child Child { get; set; }
public Parent(Child kid)
{
Child = kid;
}
}
答案 0 :(得分:13)
这一行
child = null;
没有做你认为的事情。它将对Child
方法所持有的TestObject()
对象的引用置零,但它对Child
对象所持有的同一Parent
对象的引用没有影响:
在分配child = null
之前:
指定child = null
后:
这就是为什么
Assert.IsNull(parent.Child);
失败:parent.Child
引用与您排除的child
引用不同。
另一方面,如果您执行child.Name = null
,那么parent.Child.Name
也将成为null
:
child.Name = null;
Assert.IsNull(parent.Child.Name);
答案 1 :(得分:5)
你在引用工作方面犯了一个错误。将Child
对象传递给Parent
对象时,您将传递对该对象的引用。这意味着当您更改Child
对象上的名称时,Parent.child
会看到这些更改,因为它是对同一对象的引用。当时,您的child
变量和Parent.child
属性指向相同的引用,这就是为什么设置名称会以您期望的方式更改它的原因。但是,当您将child
设置为null时,您正在更改它的引用,它现在指向没有对象(null),但您还没有做任何操作来操作{{1}的引用指向它,它仍然具有对原始对象的引用,因此它不会更改为null,因为您在设置Parent.child
时所做的就是删除对象的引用,而不是以任何方式更改对象。就像你有
child = null
在这种情况下, Child child2 = child;
child = null;
不会设置为child2
,因为对象null
指向的是原始的child2
引用,而您所做的一切删除使用引用,而不是自己操纵引用。
答案 2 :(得分:3)
Child属性是对内存中实际Child对象的引用。您的本地变量“child”是对同一对象的另一个不同引用。将本地子项设置为null时,它不会触及Parent对其的引用。 如果在任一引用上设置Name属性,那就是更改实际对象,您将看到它通过两个引用反映出来。