如何解决循环引用?

use*_*610 22 c# oop circular-dependency

如何解决循环引用问题,例如A类将B类作为其属性之一,而B类将A类作为其属性之一?

如何为这些问题做建筑师?

如果你举一个NHibernate的例子,对象之间会有一个父子关系.

它如何处理这些父子场景?

Ed *_*tes 29

在大多数情况下,当我必须互相引用两个东西时,我已经创建了一个删除循环引用的接口.例如:

之前

public class Foo
{
    Bar myBar;
}

public class Bar
{
    Foo myFoo;
}
Run Code Online (Sandbox Code Playgroud)

依赖图:

Foo     Bar
 ^       ^
 |       |
Bar     Foo
Run Code Online (Sandbox Code Playgroud)

Foo取决于Bar,但Bar也依赖于Foo.如果它们位于单独的程序集中,则构建时会出现问题,尤其是在执行干净重建时.

public interface IBar
{
}

public class Foo
{
    IBar myBar;
}

public class Bar : IBar
{
    Foo myFoo;
}
Run Code Online (Sandbox Code Playgroud)

依赖图:

Foo, IBar     IBar
    ^          ^
    |          |
   Bar        Foo
Run Code Online (Sandbox Code Playgroud)

Foo和Bar都依赖于IBar.没有循环依赖,如果将IBar放在自己的程序集中,则Foo和Bar位于不同的程序集中将不再是问题.

  • 示例代码在上面发布.如果你想要别的东西,我很困惑,也不明白.您在寻找更具体的例子吗? (2认同)
  • 这并不能真正解决循环依赖的问题。这两个实例仍将直接相互引用。同样,“ foo”和“ bar”可能是两个完全不同的模块,完全没有共同的概念(但仍在合作以完成给定的任务)。在那种情况下,让它们实现相同的接口将是一个糟糕的做法。 (2认同)
  • @Powerslave我想看看你自己的答案,展示如何解决这个问题. (2认同)
  • @Powerslave最近的评论不是来自我,但我认为您没有抓住重点。您不能总是重新设计别人的代码。我同意拥有任何形式的循环引用不是最佳实践,但是这样做不能回答OP的问题,也不会帮助陷入这种情况的其他任何人。我的回答是,所以很有用。 (2认同)
  • 是的,您错过了重点。如果您无法控制第三方代码,并且您的名字调用(例如,“作为负责任的专业人员...”)也无法更改,则没有“尝试”。您对问题的回答是不回答。这不是建设性的,也不是重复的讨论。 (2认同)

Joh*_*aft 7

我会告诉你的朋友他需要重新考虑他的设计.像你描述的循环引用通常是设计缺陷的代码味道.

  • 我真的不明白为什么这会是一个设计缺陷.您可以将XElement对象作为示例.XElement1有一个父节点XElement2,这个父节点包含XElement1. (5认同)
  • @ Jean-Philippe大多数情况下,这是一个设计缺陷; 不总是.即使在您的示例中,也没有循环引用,因为它们都是XElements.安东戈戈列夫的例子就是OP所谈论的内容.这是糟糕设计的一个例子. (2认同)

Ant*_*lev 5

与C++(例如)不同,C#不需要前向声明来解析循环引用.因此:

public class A
{
    public B B { get;set; }
}

public class B
{
    public A A { get;set; }
}
Run Code Online (Sandbox Code Playgroud)

然而,这通常是可疑设计决策的指标.