如何解决循环引用?

时间:2011-08-03 14:48:50

标签: c# oop circular-dependency

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

如何为这些问题做架构师?

如果以NHibernate为例,对象之间将存在父子关系。

如何处理这些父子场景?

6 个答案:

答案 0 :(得分:28)

在大多数情况下,当我必须互相引用两件事时,我创建了一个界面来删除循环引用。例如:

<强> BEFORE

public class Foo
{
    Bar myBar;
}

public class Bar
{
    Foo myFoo;
}

依赖关系图:

Foo     Bar
 ^       ^
 |       |
Bar     Foo

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

<强> AFTER

public interface IBar
{
}

public class Foo
{
    IBar myBar;
}

public class Bar : IBar
{
    Foo myFoo;
}

依赖关系图:

Foo, IBar     IBar
    ^          ^
    |          |
   Bar        Foo

Foo和Bar都依赖于IBar。没有循环依赖,如果将IBar放在自己的程序集中,Foo和Bar在单独的程序集中将不再是一个问题。

答案 1 :(得分:6)

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

答案 2 :(得分:5)

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

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

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

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

答案 3 :(得分:1)

在大多数情况下,最好的解决方案是改变您的设计并避免循环依赖。例如,您可以执行以下操作之一:

  1. 将公共引用代码移动到解决方案中的实用程序项目,并让其他项目引用实用程序项目
  2. 在答案中使用“Ed Bayiates”所解释的界面。
  3. 如果是少量简单/公共代码,则为其中一个类重写它,这样您就不需要以循环依赖方式引用它。 (我最不喜欢的)
  4. 但是,如果您正在使用许多项目的解决方案,并且由于您不拥有代码而无法进行上述更改之一,那么它很难实现,或者不值得花时间要修复,那么您可以使用此方法:

    右键单击项目引用,然后选择“添加引用...”。然后在出现的对话框窗口中切换到“浏览”选项卡和“浏览”按钮。从那里你可以找到DLL并选择它。这是最好的解决方案,并且可能导致构建问题,尤其是如果两个DLL都经常更新和/或具有许多依赖项。我不推荐这种方法,但它适用于捏。

    Fissh

答案 4 :(得分:0)

接口是一个好主意但是如果你寻找一个更快的解决方案,而不是重做这么多东西的架构,试着构建一个包含所有数据结构的dll类库,你的主项目会保存你需要该数据的UI,然后是其他任何你想要添加的dll也可以访问那些数据结构dll,因此它们具有运行所需的所有信息,但仍然可以分开 - 这称为三力设计模式 -

答案 5 :(得分:0)

当两个或更多相互依赖的资源导致锁定条件时,发生循环引用。这使资源无法使用。

要处理C#中的循环引用问题,应使用垃圾回收。它检测并收集循环引用。垃圾收集器从局部和静态开始,并标记可以通过其子级访问的每个对象。

通过此操作,您可以使用循环引用来解决问题。

假设以下类是循环引用。在这里,他们彼此依赖-

public class A
        {
            B Two;
        }
public class B
        {
            A one;
        }

要解决此问题,请创建一个接口-

public interface myInterface {
}

public class A {
   myInterface Two;
}

public class B: myInterface {
   A one;
}