2009-02-01 129 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; 
}