编程小知识之 循环依赖

49 篇文章 1 订阅

本文简述了一些循环依赖的知识~

之前工作中遇到了循环依赖的问题,在此简单记录一些相关的知识~

拿 Lua(5.3) 举例,如果我们循环 require 模块,就会触发堆栈溢出错误:

-- module_1.lua
require("module_2")
return {}
-- module_2.lua
require("module_1")
return {}
-- test.lua
-- cause stack overflow here ...
require("module_1")

使用 Lua require 的模块只有两种状态: 未加载已加载,并没有所谓的 部分加载 的概念,这也导致了 Lua require 不能处理循环依赖问题,类似的,我们也可以看看 C# 中涉及循环依赖的表现:

我们都知道 C# 中类的静态构造函数在创建第一个类型实例或者引用类型任一静态成员之前会被调用,据此,我们可以编写两个相互引用的静态构造函数来进行循环依赖的测试:

class ClassA
{
    public static int s_value;

    static ClassA()
    {
        s_value = ClassB.s_value;
    }
}

class ClassB
{
    public static int s_value;

    static ClassB()
    {
        s_value = ClassA.s_value;
    }
}

static void Main(string[] args)
{
    Console.WriteLine(ClassA.s_value);
    Console.WriteLine(ClassB.s_value);
}

也许你会猜测上述代码也会产生堆栈溢出之类的问题,但实际上,程序会正常输出 0 0,原因在于 C# 并不会重复执行类的静态构造函数,哪怕类的静态构造函数还没有执行完成(正在执行),简单来说, C# 中类的静态构造函数可以处理循环依赖的问题,只是执行结果可能并不直观:

(有兴趣的朋友可以考虑看看下面这个测试程序的输出结果)

class ClassA
{
    public static int s_value = 1;

    static ClassA()
    {
        s_value = ClassB.s_value;
    }
}

class ClassB
{
    public static int s_value = 2;

    static ClassB()
    {
        s_value = ClassA.s_value;
    }
}

static void Main(string[] args)
{
    Console.WriteLine(ClassA.s_value);
    Console.WriteLine(ClassB.s_value);
}

解决循环依赖的一个通用方法就是抽取公用模块,让循环依赖的模块解耦,转而共同依赖于这个公用模块,举例来说:

譬如 模块 A 依赖于 模块 B(需要使用 B.Func), 模块 B 也依赖于 模块 A(需要使用 A.Func),则我们抽取出 模块 C(其具有 A.Func 和 B.Func 的功能),然后让 模块 A 和 模块 B 去除相互依赖,转而都去依赖 模块 C.

更多资料
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值