从实例外部将属性设置为null

时间:2015-04-03 13:26:42

标签: c# .net

我发现了以下我很难理解的行为。

我假设你可以将对象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;
        }
    }

3 个答案:

答案 0 :(得分:13)

这一行

child = null;

没有做你认为的事情。它将对Child方法所持有的TestObject()对象的引用置零,但它对Child对象所持有的同一Parent对象的引用没有影响:

在分配child = null之前:

Before the change

指定child = null后:

After the change

这就是为什么

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属性,那就是更改实际对象,您将看到它通过两个引用反映出来。