C#中替代嵌套循环遍历未知深度ISymbol集合的方法
解决未知深度ISymbol嵌套结构的遍历问题
针对未知深度的ISymbol嵌套结构,不需要使用反射——接口已经明确提供了SubSymbols属性,直接通过递归遍历或**迭代遍历(避免栈溢出)**就能完美适配任意嵌套层级,收集所有InstancePath到列表中。
方案1:递归实现(代码简洁,适合常规深度场景)
递归逻辑直观:处理当前Symbol,然后递归处理它的所有子Symbol,直到没有子Symbol为止。同时利用IsRecursive属性配合已处理集合,避免循环引用导致的无限递归:
public static List<string> SymbolsCollection(AdsClient adsClient) { List<string> symbols = new List<string>(); ISymbolCollection<ISymbol> symbolCollection = GetSymbols(adsClient); // 记录已处理的Symbol,防止循环引用和重复添加 HashSet<ISymbol> processedSymbols = new HashSet<ISymbol>(); foreach (ISymbol symbol in symbolCollection) { TraverseSymbol(symbol, symbols, processedSymbols); } return symbols; } private static void TraverseSymbol(ISymbol symbol, List<string> symbols, HashSet<ISymbol> processedSymbols) { // 跳过已处理的Symbol if (!processedSymbols.Add(symbol)) return; symbols.Add(symbol.InstancePath); // 遍历所有子Symbol并递归处理 foreach (ISymbol subSymbol in symbol.SubSymbols) { TraverseSymbol(subSymbol, symbols, processedSymbols); } }
方案2:迭代实现(深度优先,避免栈溢出,适合极深嵌套场景)
如果嵌套层级极深(比如超过1000层),递归可能引发栈溢出,这时可以用栈模拟递归过程:
public static List<string> SymbolsCollection(AdsClient adsClient) { List<string> symbols = new List<string>(); ISymbolCollection<ISymbol> symbolCollection = GetSymbols(adsClient); HashSet<ISymbol> processedSymbols = new HashSet<ISymbol>(); Stack<ISymbol> symbolStack = new Stack<ISymbol>(); // 初始化栈,加入所有顶层Symbol foreach (ISymbol symbol in symbolCollection) { if (processedSymbols.Add(symbol)) symbolStack.Push(symbol); } while (symbolStack.Count > 0) { ISymbol currentSymbol = symbolStack.Pop(); symbols.Add(currentSymbol.InstancePath); // 反向压栈,保证遍历顺序和递归一致(可选,不影响结果完整性) foreach (ISymbol subSymbol in currentSymbol.SubSymbols.Reverse()) { if (processedSymbols.Add(subSymbol)) symbolStack.Push(subSymbol); } } return symbols; }
关键注意事项
- 循环引用处理:通过
HashSet<ISymbol>记录已处理的Symbol实例,结合接口的IsRecursive属性,可有效避免无限遍历和重复添加。 - 兼容性:两种方案同时兼容.NET 6和.NET Framework 4.8,无需切换框架即可直接使用。
- 性能选择:迭代方式在极深嵌套下性能更稳定,递归方式代码更简洁易读,可根据实际场景灵活选择。
原代码问题说明
你当前的嵌套foreach属于固定深度遍历,只能处理3层嵌套,当客户端返回的Symbol层级超过3层时,深层的InstancePath会被遗漏。上述两种方案都能动态适配任意嵌套深度,完全解决该问题。
内容的提问来源于stack exchange,提问作者ziga
相关产品推荐
相关产品推荐

