2009-02-01 138 views
2

我有一種情況,對象A有一個對象B的引用.B也有一個引用回到A.爲簡單起見,假設A和B是相同類型的。如何確保當我更新A上的參考時,更新也會反映在B上(反之亦然)?保持對象圖一致

這種類型的接口的例子:

interface IGraphNode 
{ 
    IGraphNode From { get; set; } 
    IGraphNode To { get; set; } 
} 

執行下面的代碼後,我希望B.From返回A.

IGraphNode A = new GraphNode(); 
IGraphNode B = new GraphNode(); 
A.To = B; 

回答

1
IGraphNode From 
{ 
    get { return from; } 
    set 
    { 
     from = value; 
     if (value.To != this) { 
      value.To = this; 
     } 
    } 
} 

IGraphNode To 
{ 
    get { return to; } 
    set 
    { 
     to = value; 
     if (value.From != this) { 
      value.From = this; 
     } 
    } 
} 

您可能希望將其與一個檢查,如果(價值==本),但延長...

,如果你執行你永遠不能使用IGraphNode對於非圓形的東西循環引用..

0

你必須明確地設置:

A.To = B; 
B.From = A; 

就此而言,這是可能的。大多數面向對象的語言都透明地處理這些循環引用。

如果您希望自動進行雙向引用,則可以始終擴展您的IGraphNode接口,並在您的From和To屬性中創建一個抽象基類,該屬性在修改時設置其他值。所有需要這種自動功能的GraphNode應該擴展基本的抽象類。

+0

理想情況下,應該是自動的 - 怎麼會你執行這個? – 2009-02-01 08:52:03

+0

難道你不是指「大多數面向對象的語言不能透明地處理這些循環引用」嗎? – 2009-02-01 08:53:29

0

您需要有鏈接的通知B,可能只需設置B.From屬性即可。

但是,你需要考慮的事情一樣,如果有什麼多個對象得到一個鏈接到B:

IGraphNode A = new GraphNode(); 
IGraphNode B = new GraphNode(); 
IGraphNode C = new GraphNode(); 

A.To = B; 
C.To = B; 

// what should B.From return? 

而且,想想會發生什麼,如果引用的對象之一是未引用?例如:

IGraphNode A = new GraphNode(); 
IGraphNode B = new GraphNode(); 

A.To = B; 
A = null; // should the reference from B keep the object 
      // that A used to reference alive? 

WeakReference對象而不是直接引用可能有助於解決此特定問題。

0

雖然接受的答案很聰明,但我不是它的粉絲。特別是關於修改屬性內的「值」的部分。 方法/屬性不應該有隱藏的副作用。像這樣的做法通常會導致難以追查的意外行爲。期望在A上調用一個屬性會修改我的B對象是不自然的。如果我明確地檢查了代碼,我只知道這一點?很多時候,源代碼甚至不可用。

一個更好的解決方案是創建一個進行的操作和任何副作用的顯式方法更爲明顯,例如:

void ConnectNodes(IGraphNode a, IGraphNode b) 
{ 
    a.to = b; 
    b.from = a; 
} 

void ConnectNodes(IGraphNode b) 
{ 
    this.to = b; 
    b.from = this; 
}