13.C#泛型写法问题

  1. 13.CSharp泛型写法问题
    1. 13.1 题目
    2. 这句C#代码是否有问题,为什么?csharp IList<IList<int>> list = new List<List<int>>();
    3. 13.2 深入解析
    4. 13.3 答题示例
    5. 13.4 关键词联想

13.CSharp泛型写法问题


13.1 题目

这句C#代码是否有问题,为什么?
csharp IList<IList<int>> list = new List<List<int>>();

13.2 深入解析

这句代码编译会报错

举例说明:
如果允许以下代码:

IList<IList<int>> list = new List<List<int>>();

那么通过 IList<IList<int>> 视图向其中添加「任意 IList<int>」时,可能加入并非 List<int> 的实例,破坏底层 List<List<int>> 的类型约定。例如(仅作类型安全说明,实际因不变性上述赋值无法编译):

// 若错误地允许协变:`int[]` 实现 IList<int>,但并非 List<int>
list.Add(new int[10]);

原因:泛型协变性和逆变性的问题

  • 协变(Covariance):允许子类型赋值给父类型,通常用于 out 类型参数;
  • 逆变(Contravariance):允许父类型赋值给子类型,通常用于 in 类型参数。

IList<T> 既包含“获取”操作(返回 T,可能需要协变),又包含“设置”操作(接受 T,可能需要逆变),因此它既不能是协变的,也不能是逆变的,只能是不变的


13.3 答题示例

“这句代码有问题,会导致编译错误。原因在于C#泛型的不变性IList<T> 接口既包含输出操作(如返回 Tthis[int]),又包含输入操作(如接受 TAdd 方法),因此它是不变接口,不支持协变或逆变转换。

具体来说,List<List<int>> 不能赋值给 IList<IList<int>>——虽然 List<int> 实现 IList<int>,但 IList<T>T不变的:不能把这种“嵌套泛型”的实例当成外层接口的另一种类型实参。若放宽为可赋值,则可通过 IList<IList<int>>Add 传入任意 IList<int>(如 int[]),而实际容器仍是 List<List<int>>,破坏类型一致性。”


13.4 关键词联想

  • 泛型不变性(Invariance)
  • 协变(Covariance,out关键字)
  • 逆变(Contravariance,in关键字)
  • 类型安全(Type Safety)
  • IList<T> 双向操作(get/set)
  • 泛型接口方差(Generic Interface Variance)
  • IEnumerable<out T>(协变示例)
  • Action<in T>(逆变示例)
  • 子类型泛型赋值限制


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏