C#解析渠道编码映射报capacity相关System.ArgumentOutOfRangeException异常
异常触发原因说明
你遇到的System.ArgumentOutOfRangeException: capacity was less than the current size. (Parameter 'value'),可以直接排除是字符串分割、类型转换、枚举强转这些常规操作触发的——这个异常是.NET内置List<T>类型的固定校验逻辑抛出的。
触发这个异常的唯一条件是:对
List<T>的Capacity属性赋值时,传入的目标容量值小于列表当前实际存储的元素数量(即Count属性的当前值)。
结合当前代码的常见触发路径
- 最常见场景:
this.boxes是类级别的全局共享列表,没有做线程安全保护,存在跨线程并发操作。比如当前方法正在循环往列表中Add元素(此时列表的Count已经增长到比如6),另一个业务逻辑分支正在给这个列表的Capacity设置一个小于6的值(比如4),就会立刻触发这个校验异常。 - 次要场景:你在类的其他位置(不在当前方法内)显式给
this.boxes设置过固定初始容量,且在某次赋值时没有等列表清空实际元素数量,就直接修改了Capacity属性,触发校验失败。
适配业务需求的修正方案
针对你“分号切分整体映射串、每个分段按逗号拆成通道号和盒数映射、判断所有映射的盒数是否完全一致(即单盒模式)”的需求,可按以下逻辑调整代码,从根源规避异常:
- 把遍历过程中的共享列表操作改成方法内局部变量操作,所有解析完成后再统一同步全局列表状态,避免遍历过程中被其他线程篡改:
private bool DetermineWhetherInSingleBoxModeFromChannelCodeMappings(string channelCodeToBoxesMapping) { // 解析阶段用局部变量,不操作全局共享对象 var parsedBoxValues = new List<BoxCount.Boxes>(); if (string.IsNullOrWhiteSpace(channelCodeToBoxesMapping)) { this.boxes.Clear(); return false; } var channelCodeAndBoxPairs = channelCodeToBoxesMapping.Split(';', StringSplitOptions.RemoveEmptyEntries); foreach (var pair in channelCodeAndBoxPairs) { var channelCodeAndBoxSplit = pair.Split(',', StringSplitOptions.RemoveEmptyEntries); // 跳过格式不符合预期的分段 if (channelCodeAndBoxSplit.Length != 2) { continue; } // 用TryParse替代直接Convert,避免非数字值触发转换异常 if (!short.TryParse(channelCodeAndBoxSplit[1], out var numericBoxValue)) { continue; } parsedBoxValues.Add((BoxCount.Boxes)numericBoxValue); } // 所有解析完成后再统一更新全局列表状态 this.boxes.Clear(); this.boxes.AddRange(parsedBoxValues); // 判断所有解析到的盒数是否唯一 return this.boxes.Distinct().Count() == 1; }
- 如果业务上必须保留全局列表的即时操作,所有涉及
this.boxes的读写逻辑都要加互斥锁,避免并发操作引发的容量校验冲突。
内容的提问来源于stack exchange,提问作者Bhav
相关产品推荐
相关产品推荐

