List添加对象触发StackOverflowException问题求助
异常信息
StackOverflowException: The requested operation caused a stack overflow. System.Collections.Generic.List'1[T].set_Capacity (System.Int32 value) (at <6073cf49ed704e958b8a66d540dea948>:0)
System.Collections.Generic.List'1[T].EnsureCapacity (System.Int32 min) (at <6073cf49ed704e958b8a66d540dea948>:0)
System.Collections.Generic.List'1[T].AddWithResize (T item) (at <6073cf49ed704e958b8a66d540dea948>:0)
代码片段
public List<Object> MyObjects; public List<Object> AllObjectsExcluding(string excludedObjectId) { List<Object> objects = new List<Object>(); foreach (Object @object in MyObjects) { if (@object.id != excludedObjectId) { objects.Add(@object); //StackOverflowException } } return objects; } public class Object { public string id; }
问题原因分析
从异常栈和代码来看,栈溢出的核心原因是无限递归耗尽了栈内存,结合代码细节,可能的触发场景包括:
id访问触发递归循环
如果你的Object类中id实际是属性而非字段,且属性的get方法内部递归调用了AllObjectsExcluding(或间接触发该方法执行),会形成无限循环:遍历MyObjects时访问object.id,id的getter调用AllObjectsExcluding,该方法再次遍历MyObjects并访问object.id,不断消耗栈内存直至溢出。关键字变量名引发的解析异常
foreach循环中使用了object作为变量名,这是C#的保留关键字。虽然编译器允许上下文解析,但可能导致意外的逻辑混淆,间接触发异常。自定义类与系统类型冲突
你自定义的类名Object与System.Object重名,若未明确指定命名空间,编译器可能将List<Object>解析为List<System.Object>,导致元素类型不匹配。不过这种情况通常会引发编译错误,而非运行时栈溢出,可能性较低。MyObjects包含递归引用元素
若MyObjects列表中存在元素间接引用了列表自身(比如某个元素的属性指向MyObjects),且遍历或添加时触发了对该引用的递归解析,也可能导致栈溢出。但List的Add方法仅存储引用,不会主动解析元素内部结构,需结合额外逻辑才会触发。
修复建议
- 修改foreach循环的变量名,将
object改为@object或obj,避免关键字冲突。 - 检查
Object类的id定义:若为属性,确认其get方法无递归调用逻辑,若有则移除。 - 确保
MyObjects列表中不存在递归引用的元素,比如不要将列表自身或包含列表的对象添加到列表中。 - 为自定义
Object类添加命名空间,明确区分于System.Object,避免类型混淆。
内容的提问来源于stack exchange,提问作者Maksim Chesnokov

