C#中为何无法返回List<List<T>>匹配IList<IList<T>>返回类型?
为什么List<List>无法转换为IList<IList>?
首先得明确一个关键规则:C#里的IList<T>是不变泛型接口,只有标记了out(协变)或in(逆变)的泛型接口,才支持子类型到父类型的隐式转换。比如IEnumerable<out T>是协变的,所以你可以把List<string>隐式转成IEnumerable<object>,但IList<T>没有这些标记,所以不支持这类转换。
为什么这种转换会被禁止?
假设编译器允许把List<List<string>>转成IList<IList<string>>,会触发类型安全问题:
- 你拿到
IList<IList<string>>类型的变量后,理论上可以往里面添加任何实现了IList<string>的对象,比如自定义的MyStringList : IList<string>。 - 但实际这个变量指向的是
List<List<string>>,它只能容纳List<string>类型的元素,强行添加MyStringList会在运行时抛出类型转换异常。
为了避免这种运行时错误,编译器直接在编译阶段就禁止了这种转换。
为什么返回List<IList>是有效的?
List<IList<string>>的元素类型本身就是IList<string>,它可以容纳任何实现了IList<string>的对象(包括List<string>)。而List<T>本身实现了IList<T>,这里的T是IList<string>,所以List<IList<string>>完全符合IList<IList<string>>的接口要求,自然可以直接返回。
解决方法
如果要返回符合IList<IList<string>>类型的对象,有两种常见方式:
- 直接创建
List<IList<string>>并添加元素:IList<IList<string>> Foo() { var result = new List<IList<string>>(); result.Add(new List<string>()); // List<string>是IList<string>的实现,可直接添加 return result; } - 如果已有
List<List<string>>,可以通过LINQ转换为List<IList<string>>:IList<IList<string>> Foo() { var listOfLists = new List<List<string>>(); // 添加元素到listOfLists return listOfLists.Cast<IList<string>>().ToList(); }
内容的提问来源于stack exchange,提问作者kashiashvili
相关产品推荐
相关产品推荐

