You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在函数中使用任意类型,实现递归引用循环检查方法的通用化

你可以通过泛型参数+抽离类型耦合逻辑的方式实现通用的循环引用检查方法,以下是两种可直接落地的实现方案:

方案1:委托适配方案(无类型侵入,适配所有层级结构类型)

把和具体类型绑定的唯一标识判断、子节点加载、子节点获取逻辑抽为委托参数,不需要修改原有类的定义,适配性最高:

/// <summary>
/// 通用层级结构循环引用检查方法
/// </summary>
/// <typeparam name="T">待检查的层级节点类型</typeparam>
/// <param name="currentObj">当前检查的节点对象</param>
/// <param name="visitStack">已访问节点栈</param>
/// <param name="existCheck">判断当前节点是否已存在于访问栈的逻辑</param>
/// <param name="loadChildItems">加载当前节点子节点的逻辑</param>
/// <param name="getChildItems">获取当前节点子节点集合的逻辑</param>
/// <returns>是否存在循环引用</returns>
private bool CheckReferenceLoop<T>(T currentObj, List<T> visitStack, 
    Func<T, bool> existCheck, 
    Action<T> loadChildItems, 
    Func<T, IEnumerable<T>> getChildItems)
{
    bool haveLoop = false;
    if (existCheck(currentObj))
    {
        haveLoop = true;
    }
    else
    {
        visitStack.Add(currentObj);
        loadChildItems(currentObj);
        foreach (var child in getChildItems(currentObj))
        {
            if (!haveLoop)
            {
                haveLoop = CheckReferenceLoop(child, visitStack, existCheck, loadChildItems, getChildItems);
            }
        }
        // 可选:如果需要复用visitStack实例,可添加回溯逻辑
        // visitStack.RemoveAt(visitStack.Count - 1);
    }
    return haveLoop;
}

对应你原有Organization场景的调用示例:

Data.DataContext db = new Data.DataContext();
Organization targetOrg = 获取待检查的根节点();
var visitStack = new List<Organization>();

bool hasLoop = CheckReferenceLoop(
    currentObj: targetOrg,
    visitStack: visitStack,
    existCheck: obj => visitStack.Find(a => a.Id == obj.Id) != null,
    loadChildItems: obj => obj.GetChildItems(db),
    getChildItems: obj => obj.ChildItems
);

方案2:接口约束方案(适合多类统一实现层级结构的场景)

如果项目中大量需要做循环检查的层级类可以统一实现公共接口,可通过泛型约束简化调用逻辑,减少重复传参:
首先定义统一的层级节点接口:

public interface IHierarchyNode<out T>
{
    // 节点唯一标识,可根据实际场景调整类型为Guid/string等
    int Id { get; }
    // 子节点集合
    IEnumerable<T> ChildItems { get; }
    // 加载子节点的方法,可根据实际场景调整入参
    void GetChildItems(Data.DataContext db);
}

让你的Organization类实现上述接口后,可直接使用约束后的泛型方法:

private bool CheckReferenceLoop<T>(T currentObj, List<T> visitStack, Data.DataContext db) 
    where T : IHierarchyNode<T>
{
    bool haveLoop = false;
    if (visitStack.Find(a => a.Id == currentObj.Id) != null)
    {
        haveLoop = true;
    }
    else
    {
        visitStack.Add(currentObj);
        currentObj.GetChildItems(db);
        foreach (var child in currentObj.ChildItems)
        {
            if (!haveLoop)
            {
                haveLoop = CheckReferenceLoop(child, visitStack, db);
            }
        }
    }
    return haveLoop;
}

调用时直接传入参数即可,不需要额外传委托:

var visitStack = new List<Organization>();
bool hasLoop = CheckReferenceLoop(targetOrg, visitStack, db);

可选性能优化

如果需要检查的层级结构节点数量较多,可将访问栈从List<T>替换为HashSet<int>(存储节点Id),将存在性判断的时间复杂度从O(n)降低到O(1),大幅提升检查效率。

内容的提问来源于stack exchange,提问作者Acces969

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 23:51:00