Unity中继承Collection<T>的自定义集合Add报错,求原因与解决原理
关于Collection子类使用params构造函数引发只读异常的问题解答
1. 使用params关键字的问题出在哪?
params本身没有问题,问题出在你直接将params生成的数组传给了Collection<T>的基类构造函数。Collection<T>的这个构造函数接收IList<T>类型参数,而数组虽然实现了IList<T>,但它是固定大小的集合——数组不支持动态添加/删除元素,其IList<T>接口中的Add、Remove等修改集合大小的方法会直接抛出NotSupportedException。当你调用Selection.Add()时,最终会调用底层数组的Add方法,因此触发了异常。
2. params是否会创建数组?若会,为何将数组作为IList传入不行?为何无编译错误?
- params确实会创建数组:当你调用构造函数时传入多个参数(比如
new Selection(a, b, c)),编译器会自动把这些参数打包成一个T[]数组;如果直接传入一个已有的T[]数组,也会直接使用该数组作为参数。 - 数组作为IList
传入不行的原因 :数组实现的IList<T>是固定大小的,虽然它的IsReadOnly属性返回false,但它根本不支持修改集合大小的操作。Collection<T>的底层逻辑依赖传入的IList<T>支持动态修改,而数组无法满足这个要求。 - 无编译错误的原因:编译器只做类型匹配检查——数组确实实现了
IList<T>接口,因此编译阶段不会报错。只有在运行时,调用到数组不支持的Add方法时,才会抛出异常。
3. 为何LINQ的ToList()方法能解决问题?
ToList()方法会把数组中的元素复制到一个全新的List<T>实例中。List<T>是.NET框架中标准的可动态修改集合,它完整实现了IList<T>接口的所有方法,包括Add、Remove等修改操作。当你把List<T>传给Collection<T>的构造函数后,Collection<T>的所有修改操作都会调用List<T>的对应方法,自然不会再抛出“集合只读”的异常。
内容的提问来源于stack exchange,提问作者Fraspo
相关产品推荐
相关产品推荐

