C#递归实现BOM物料清单各层级步长10流水序号设置咨询
C# 实现BOM物料清单层级按规则生成序列编号方案
核心实现思路
- 层级跟踪:递归函数传入
currentLevel参数,每进入下一级子项递归时参数+1,返回上一级时自动恢复,无需额外维护 - 层级计数器管理:使用
Dictionary<int, int>存储每个层级的当前序列值,仅维护当前遍历路径上的层级计数,切换父项时自动重置子层级的初始值,避免不同父项的子序列互相干扰
完整代码实现
1. BOM实体定义
public class BomItem { /// <summary> /// 物料ID /// </summary> public int Id { get; set; } /// <summary> /// 父物料ID,顶层物料默认值为0 /// </summary> public int ParentId { get; set; } /// <summary> /// 物料所在层级 /// </summary> public int Level { get; set; } /// <summary> /// 生成的序列值 /// </summary> public int SequenceNumber { get; set; } /// <summary> /// 子物料列表 /// </summary> public List<BomItem> Children { get; set; } = new List<BomItem>(); }
2. 序列生成核心逻辑
public class BomNumberGenerator { /// <summary> /// 层级计数器,key为层级,value为当前层级已生成的最新序列值 /// </summary> private readonly Dictionary<int, int> _levelCounter = new Dictionary<int, int>(); // 序列规则配置:起始值10,步长10 private const int StartNumber = 10; private const int Step = 10; /// <summary> /// 入口方法:传入顶层BOM集合生成序列 /// </summary> public void GenerateSequenceNumbers(List<BomItem> rootItems) { _levelCounter.Clear(); // 顶层物料默认层级为1 RecursiveGenerate(rootItems, 1); } /// <summary> /// 递归生成序列 /// </summary> private void RecursiveGenerate(List<BomItem> items, int currentLevel) { foreach (var item in items) { // 计算当前项的序列值 if (!_levelCounter.ContainsKey(currentLevel)) { _levelCounter[currentLevel] = StartNumber; } else { _levelCounter[currentLevel] += Step; } item.SequenceNumber = _levelCounter[currentLevel]; item.Level = currentLevel; // 处理子项前清空所有更深层级的计数器,保证下一级序列从10重新开始 var higherLevels = _levelCounter.Keys.Where(k => k > currentLevel).ToList(); foreach (var level in higherLevels) { _levelCounter.Remove(level); } // 递归处理子项,层级+1 if (item.Children.Any()) { RecursiveGenerate(item.Children, currentLevel + 1); } } } }
3. 调用示例
// 构造符合你示例的BOM树形结构 var root1 = new BomItem { Id = 1 }; var child2_1 = new BomItem { Id = 2 }; var child2_2 = new BomItem { Id = 5 }; var child2_3 = new BomItem { Id = 11 }; root1.Children.AddRange(new[] { child2_1, child2_2, child2_3 }); var child3_1 = new BomItem { Id = 3 }; var child3_2 = new BomItem { Id = 4 }; child2_1.Children.AddRange(new[] { child3_1, child3_2 }); var child3_3 = new BomItem { Id = 6 }; var child3_4 = new BomItem { Id = 8 }; child2_2.Children.AddRange(new[] { child3_3, child3_4 }); var child4_1 = new BomItem { Id =7 }; child3_3.Children.Add(child4_1); var child4_2 = new BomItem { Id =9 }; var child4_3 = new BomItem { Id =10 }; child3_4.Children.AddRange(new[] { child4_2, child4_3 }); var child3_5 = new BomItem { Id =12 }; child2_3.Children.Add(child3_5); var root2 = new BomItem { Id =13 }; var root3 = new BomItem { Id =14 }; var rootItems = new List<BomItem> { root1, root2, root3 }; // 执行序列生成 var generator = new BomNumberGenerator(); generator.GenerateSequenceNumbers(rootItems);
运行后所有BomItem的SequenceNumber和你提供的示例表格完全一致。
性能说明
该实现时间复杂度为O(n),n为BOM总项数,字典操作均为O(1)复杂度,递归深度最多15层远低于C#默认栈深度限制,几千行数据处理无性能压力。如果你的原始BOM是扁平存储(仅存ParentId无Children集合),先按ParentId分组构建树形结构再调用上述方法即可。
内容的提问来源于stack exchange,提问作者André Cooke
相关产品推荐
相关产品推荐

