我有一种情况,其中对象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;
答案 0 :(得分: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;
}
}
}
您可能希望通过检查if(value == this)...
来扩展它但是,如果您强制执行循环引用,则永远不能将IGraphNode用于非循环引用...
答案 1 :(得分:0)
您必须明确设置:
A.To = B;
B.From = A;
只要有可能,就是这样。大多数面向对象的语言透明地处理循环引用,例如这些。
如果您希望自动进行这种双向引用,您可以随时扩展IGraphNode接口并创建一个抽象基类,其中包含From和To属性中的一些代码,这些代码在修改时设置另一个值。需要此自动功能的所有GraphNode都应扩展基本抽象类。
答案 2 :(得分:0)
您需要拥有链接的A通知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对象而不是直接引用可能有助于解决此特定问题。
答案 3 :(得分: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;
}