2015-04-03 61 views
4

我已經確定了以下難以理解的行爲。將屬性從實例外部設置爲空

我假定您可以將對象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

「崩潰」並沒有真正告訴我們任何事情。異常更有用。 – 2015-04-03 13:29:55

+1

將'child'設置爲null只是設置局部變量'child'。 'parent.Child'仍然指向構造'parent'時分配給'child'的實例。 – 2015-04-03 13:31:13

+0

的確兒童被設置爲空而不是parent.child。如果你將parent.child設置爲null,它將按照你的意圖工作。 – 2015-04-03 13:34:07

回答

13

此行

child = null; 

沒有做什麼,你認爲它。它空值出來的參考Child對象,你TestObject()法保留,但對參考本Parent對象持相同Child對象沒有影響:您分配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); 
+0

我認爲在這種情況下,一旦Parent對象被銷燬,GC將只收集Child對象? – Keysharpener 2015-04-03 13:45:33

+0

@Keysharpener絕對! GC不會收集對象,直到最後一次到達對象的引用消失。如果將'parent'設置爲'null',則引用'parent.Child'將變得無法到達,因此'Parent'和'Child'都將符合GC的條件。 – dasblinkenlight 2015-04-03 13:47:38

3

Child屬性是在內存中的實際子對象的引用。你的本地變量「child」是對同一個對象的另一個不同的引用。當您將您的本地孩子設置爲空時,它不會觸及父母對其的引用。 如果您在任一引用上設置了Name屬性,那麼這將更改實際對象,並且您會看到它通過兩個引用都反映出來。

5

你在引用的工作方式上犯了一個錯誤。當您將Child對象傳遞給Parent對象時,您正在傳遞對該對象的引用。這意味着當您更改Child對象的名稱時,Parent.child會看到這些更改,因爲它是對同一對象的引用。當時,您的child變量和Parent.child屬性指向相同的引用,這就是設置名稱以您期望的方式更改它的原因。但是,如果將child設置爲null,則您正在更改它的引用,它現在指向沒有對象(null),但是您還沒有做任何操作Parent.child指向的引用,它仍然具有對原始對象的引用,所以它不會更改爲空,因爲您在設置child = null時所做的全部操作都是刪除對象的引用,而不是以任何方式更改對象。這是一樣的,如果你有

Child child2 = child; 
child = null; 

在這種情況下child2不會被設置爲null,因爲child2所指向的對象是原child參考,你所做的一切是刪除使用的參考,而不是自己操縱參考。