如何用C#和LINQ实现递归子项列表分配?
问题描述
类定义
public class MyModel { public Options MyOptions { get; set; } } public class Options { public IEnumerable<Options> Children { get; set; } public string SecondaryOptions { get; set; } }
尝试的递归实现(存在子项丢失问题)
public static MyModel MapDetails() { MyOptions.Children.Foreach(x => if(!string.IsNullorEmtpy(x.SecondaryOptions)) { x.Children = GetChild(x.SecondaryOptions, x); }); } public static IEnumerable<Options> GetChild(string path, Options child) { var childlist = optionsList; //基于path获取该列表 childlist.Children.Foreach(child => if(!string.IsNullorEmtpy(child.SecondaryOptions)) { //需递归调用每个子项 child.Children = GetChild(child.SecondaryOptions, child); }); }
需求与期望结构
遍历每个Options项,若其SecondaryOptions不为空或空字符串,则根据该字符串获取对应的子项列表并赋值给该项的Children属性,最终得到如下层级结构:
MyOptions.Children- A aa aaa aab ab ac B ba bb C
解决方案
原代码的核心问题
- 语法错误:
Foreach应为ForEach(C#中List<T>的方法),string.IsNullorEmtpy拼写错误,正确为string.IsNullOrEmpty;且IEnumerable<T>本身没有ForEach方法,直接调用会报错。 - 递归逻辑错误:
GetChild方法声明返回IEnumerable<Options>但未返回值,且直接修改传入对象的属性时未正确处理子项的递归赋值,导致子项丢失。 - 空值未处理:未给无
SecondaryOptions的项设置空Children,容易引发空引用异常。
正确的递归实现(结合LINQ)
// 模拟根据path获取子项的方法,需替换为真实业务逻辑 private static IEnumerable<Options> GetOptionsByPath(string path) { // 示例逻辑:根据path返回对应的子项列表 return path switch { "root" => new List<Options> { new Options { SecondaryOptions = "A" }, new Options { SecondaryOptions = "B" }, new Options() // 对应层级中的C,无SecondaryOptions }, "A" => new List<Options> { new Options { SecondaryOptions = "aa" }, new Options(), // ab new Options() // ac }, "aa" => new List<Options> { new Options(), new Options() }, // aaa、aab "B" => new List<Options> { new Options(), new Options() }, // ba、bb _ => Enumerable.Empty<Options>() }; } public static MyModel MapDetails() { var model = new MyModel(); // 构建根层级 model.MyOptions = new Options { Children = BuildHierarchy(GetOptionsByPath("root")) }; return model; } // 递归构建层级的核心方法,使用LINQ处理每个项 private static IEnumerable<Options> BuildHierarchy(IEnumerable<Options> items) { return items.Select(item => { if (!string.IsNullOrEmpty(item.SecondaryOptions)) { // 递归获取并构建当前项的子层级 item.Children = BuildHierarchy(GetOptionsByPath(item.SecondaryOptions)); } else { // 无SecondaryOptions时设置空枚举,避免null item.Children = Enumerable.Empty<Options>(); } return item; }); }
关键说明
- LINQ的
Select遍历:通过Select逐个处理每个项,确保每个节点都被递归处理,不会遗漏子项。 - 递归逻辑清晰:
BuildHierarchy专注于层级构建,数据获取逻辑抽离到GetOptionsByPath,职责分离更易维护。 - 空值安全:给无
SecondaryOptions的项设置空Children,避免后续遍历出现空引用异常。
内容的提问来源于stack exchange,提问作者Visva Kiruthika Muthuraj
相关产品推荐
相关产品推荐

