为什么泛型 IList<> 不继承非泛型 IList

2024-06-04

IList<T>不继承IList where IEnumerable<out T>继承IEnumerable.

If out修饰符是大多数实现的唯一原因IList<T> (e.g. Collection<T>, List<T>) 实现IList界面。

所以任何人都可以说好吧,如果该陈述对于所有实现都是正确的IList<T>然后直接投射到IList必要时。但问题是虽然IList<T>不继承IList所以不能保证每个IList<T>对象是IList.

此外使用IList<object>显然不是解决方案,因为没有out修饰泛型不能分配给较少继承的类;创建 List 的新实例并不是这里的解决方案,因为有人可能想要实际引用IList<T> as an IList指针;并使用List<T>代替IList<T>实际上是一种糟糕的编程习惯,并且不能满足所有目的。

如果 .NET 想要提供灵活性,那么每个实现IList<T>不应有非通用实施合同(即IList)那么为什么他们不保留另一个实现通用和非通用版本的接口,并且不建议所有想要签约通用和非遗传项目的具体类应该通过该接口签约。

铸造时也会出现同样的问题ICollection<T> to ICollection and IDictionary<TKey, TValue> to IDictionary.


正如你所注意到的,T in IList<T> is not 协变。根据经验:任何可以修改其状态的类都不能是协变的。原因是此类类通常具有以下方法:T作为其参数之一的类型,例如void Add(T element)。并且不允许使用协变类型参数input职位。

添加泛型的原因之一是为了提供类型安全。例如,您不能添加Elephant到一个列表Apple. If ICollection<T>是要延长ICollection,然后你可以打电话((ICollection)myApples).Add(someElephant)没有编译时错误,如ICollection有一个方法void Add(object obj),这似乎允许您添加any对象到列表中,而实际上您只能添加对象T。所以,ICollection<T>不延长ICollection and IList<T>不延长IList.

Anders Hejlsberg,C# 的创始人之一,像这样解释它 http://blogs.msdn.com/b/brada/archive/2005/01/18/355755.aspx:

理想情况下所有通用集合接口(例如ICollection<T>, IList<T>)将从其非泛型对应项继承,以便泛型接口实例可以与泛型和非泛型代码一起使用。

As it turns out, the only generic interface for which this is possible is IEnumerable<T>, because only IEnumerable<T> is contra-variant [sic1]: In IEnumerable<T>, the type parameter T is used only in "output" positions (return values) and not in "input" positions (parameters). ICollection<T> and IList<T> use T in both input and output positions, and those interfaces are therefore invariant.

1) IEnumerable<T> is co-variant


从 .Net 4.5 开始,有IReadOnlyCollection<out T> http://msdn.microsoft.com/en-us/library/hh881542.aspx and IReadOnlyList<out T> http://msdn.microsoft.com/en-us/library/hh192385.aspx协变接口。但IList<T>, ICollection<T>许多列表和集合类没有实现或扩展它们。坦率地说,我发现它们不是很有用,因为它们只定义了Count and this[int index].


如果我可以从头开始重新设计 .Net 4.5,我会将列表接口拆分为只读协变接口IList<out T>包括Contains and IndexOf,以及可变不变接口IMutableList<T>。然后你就可以施放IList<Apple> to IList<object>。我在这里实现了这个:

M42系列 https://bitbucket.org/Virtlink/m42-collections/- 协变集合、列表和数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么泛型 IList<> 不继承非泛型 IList 的相关文章

  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • ADO EF Code First 通用中间类继承映射

    我有以下要求 该要求在 OO 空间中运行良好 但我似乎无法首先使用 ADO EF 代码将其映射回数据库 我有许多产品 每个产品都有不同的方面 属性 但不是代码属性意义上的 例如 戒指将具有矿物类型 金等方面 而钻石将具有净度方面 VVSI1
  • 将 System.Windows.Input.KeyEventArgs 键转换为 char

    我需要将事件参数作为char 但是当我尝试转换 Key 枚举时 我得到的字母和符号与传入的字母和符号完全不同 如何正确地将密钥转换为字符 这是我尝试过的 ObserveKeyStroke this new ObervableKeyStrok
  • 存储来自其他程序的事件

    我想将其他应用程序的事件存储在我自己的应用程序中 事件示例 打开 最小化 Word 或打开文件时 这样的事可能吗 运行程序 http msdn microsoft com en us library ms813609 aspx and 打开
  • 生成(非常)大的非重复整数序列而不进行预洗牌

    背景 我编写了一个简单的媒体客户端 服务器 我想生成一个不明显的时间值 随从客户端到服务器的每个命令一起发送 时间戳中将包含相当多的数据 纳秒分辨率 即使它不是真正准确 因为现代操作系统中计时器采样的限制 等 我想做的 在 Linux 上
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 未定义的行为或误报

    我 基本上 在野外遇到过以下情况 x x 5 显然 它可以在早期版本的 gcc 下编译干净 在 gcc 4 5 1 下生成警告 据我所知 警告是由 Wsequence point 生成的 所以我的问题是 这是否违反了标准中关于在序列点之间操
  • PlaySound 可在 Visual Studio 中运行,但不能在独立 exe 中运行

    我正在尝试使用 Visual Studio 在 C 中播放 wav 文件 我将文件 my wav 放入项目目录中并使用代码 PlaySound TEXT my wav NULL SND FILENAME SND SYNC 我按下播放按钮 或
  • Visual Studio 中的测试单独成功,但一组失败

    当我在 Visual Studio 中单独运行测试时 它们都顺利通过 然而 当我同时运行所有这些时 有些通过 有些失败 我尝试在每个测试方法之间暂停 1 秒 但没有成功 有任何想法吗 在此先感谢您的帮助 你们可能有一些共享数据 检查正在使用
  • 私有模板函数

    我有一堂课 C h class C private template
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

    我正在尝试使用 Amazon Web Services 查询艺术家和标题信息并接收回专辑封面 使用 C 我找不到任何与此接近的示例 所有在线示例都已过时 并且不适用于 AWS 的较新版本 有一个开源项目CodePlex http www c
  • .NET中的LinkedList是循环链表吗?

    我需要一个循环链表 所以我想知道是否LinkedList是循环链表吗 每当您想要移动列表中的 下一个 块时 以循环方式使用它的快速解决方案 current current Next current List First 电流在哪里Linke
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 您可以严格泛型类型或为一个参数指定多个类型吗?

    例如我想指定一个类型可能是Integer or String并将其用作特殊类型func我试过typealias但它不会解决这个问题 因为类型别名不能有or参数作为其唯一用途 因此请考虑下面的情况 typealias alis StringP
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐