【问题标题】:What is difference between IList and IList<T>IList 和 IList<T> 有什么区别
【发布时间】:2012-12-22 12:03:48
【问题描述】:

.net 中List&lt;T&gt; 的定义表明它实现了各种接口。

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable

带有和不带有T 的接口会带来什么变化IList 即如果我的一个类实现IList&lt;T&gt; 而不是IList,那么我可以将它用作我的自定义集合类吗?

【问题讨论】:

    标签: c# .net generics collections


    【解决方案1】:

    List&lt;T&gt; 实现IList&lt;T&gt; 和IList 的原因是为了使它可以在您的代码假定IList 的任何地方使用。这将使过渡到通用IList&lt;T&gt; 变得更加容易,因为它更合适。此外,如果您有一个 .net 1.1 或更早版本的代码,即使您的类是在 .net 2.0 或更高版本的程序集中实现的,您也希望重用它,这将成为可能。

    【讨论】:

      【解决方案2】:

      在IList&lt;T&gt; 中,您只能放入已定义(T)类型的对象,而 IList 可以包含不同类型的对象

      由于 AdressInformation 不是客户列表中的有效对象,因此下面的代码将不符合要求

      IList<Customer> customers = new List<Customer>();
      customers.Add(new Customer());
      customers.Add(new AdressInformation());
      

      这段代码会编译,但会在运行时抛出异常

      IList customers = new List<Customer>();
      customers.Add(new Customer());
      customers.Add(new AdressInformation());
      

      【讨论】:

      • 如果我使用 IList customer = new List() 并且在那个 customer.Add("1") 之后它应该可以工作,但它仍然给我错误(在运行时)。根据定义,因为它也在实现没有 T 的 IList,所以当我在 IList 中添加任何值作为对象时它应该可以工作。
      • 那会编译,因为客户变量不是通用的。
      • 当然它在运行时会失败......这就是泛型的重点!为什么它不应该失败 - 你将列表限制为只包含 Customer 实例,所以如果你突然被允许添加字符串,世界上就没有真相了。
      • IList 只是一个接口,不是基类实现。它唯一强制的是该类实现了该公共接口。 List&lt;T&gt; 确实实现了该接口,因此可以将其转换为 IList。仅仅因为它的特定接口实现在使用无效参数调用时抛出异常并不意味着它没有实现该接口。接口没有指定实现它的类何时可以或不能抛出异常。
      • @Ikaso 编译失败并不能保证它会在运行时工作。你可以即。使用反射调用将整数传递给 IList 的 Add 方法,编译器不会知道它是不合法的。这篇博文让许多认为编译意味着测试程序是否存在缺陷的人大开眼界splitbrain.org/blog/2009-09/…
      【解决方案3】:

      问题:

      IList 和 IList&lt;T&gt; 有什么区别?

      答案:

      IList 和 IList&lt;T&gt; 都是接口,但 IList 不是通用的,它既属于并属于 System.Collections 命名空间,而 IList&lt;T&gt; 是通用的,它既属于又属于System.Collections.Generic 命名空间。

      此外,System.Collections.IList 也与 System.Collections.Generic.IList&lt;object&gt; 相同。

      由于object,在C#中,可以是任何可以在泛型类型T中使用的类型,在尖括号内,扩展object,这意味着System.Collections.IList和System.Collections.Generic.IList&lt;T&gt;有相同的表现力。

      这也说明了所有可以在System.Collections.IList接口的帮助下完成的任务,这些任务也可以在System.Collections.Generic.IList&lt;T&gt;接口的帮助下完成。

      如果是这样,那么更喜欢什么:System.Collections.IList 或 System.Collections.Generic.IList&lt;T&gt;?

      虽然System.Collections.IList 更短并且需要更少的输入,但System.Collections.Generic.IList&lt;T&gt; 仍然更好,更值得推荐,因为它使您的代码更加精确、准确、准确、正确、严格、信息丰富、解释性、详细、详尽,逐项,详细,表达,清晰,可读和易读,如果程序员在使用通用接口时犯了任何错误,那么编译可能会失败,程序员会立即知道并理解他/她做错了什么,纠正错误和客户可能会在应用程序中遇到更少的错误。

      但是不正确地使用非通用接口可能会在应用程序中产生未知的错误,客户可能会发现这些错误,使他/她不满意,向开发人员报告这些错误,还可能要求/要求/启动一个退款。

      举个例子:

      System.Collections.Generic.IList<int> list = GetSomeListOfIntegers();
      list.Add(1);
      list.Add(2);
      list.Add(3);
      list.Add("four");
      list.Add(5);
      

      上面的代码因为list.Add("four");这一行无法编译。

      该错误或多或少表明参数必须是int,但它是string。

      这有助于在构建应用程序之前查看编译器错误并纠正所有错误。这样,客户就不会在应用程序中遇到不必要的错误并保持满意。

      但是如果程序员不更改list.Add("four");这一行,那会导致编译器失败,而是将System.Collections.Generic.IList&lt;int&gt;替换为System.Collections.IList并修改方法GetSomeListOfIntegers以返回System.Collections.IList的实例而不是System.Collections.Generic.IList&lt;int&gt; 的一个实例

      那么代码就编译成功了,但是在执行list.Add("four");的时候,抛出了cast failure异常,然后应用程序停止执行并终止。

      如果所有程序员和开发人员都找不到这个 bug,谁知道哪个客户会发现这个 bug。

      这就是为什么命名空间System.Collections.Generic的所有泛型类和接口,包括IList&lt;T&gt;,都比命名空间System.Collections和@987654357的所有类和接口,包括IList好得多@ 应该是推荐的命名空间一般而言。

      从历史上看,命名空间System.Collections 以及在此命名空间中定义的所有类和接口,包括接口IList,都存在于命名空间System.Collections.Generic 及其所有类和接口(包括IList&lt;T&gt; 泛型接口)之前。

      命名空间System.Collections.Generic 及其所有类和接口是在 Microsoft 的 .NET Framework 的更高版本中引入的。

      【讨论】:

        猜你喜欢
        • 2016-02-12
        • 2015-03-21
        • 1970-01-01
        • 1970-01-01
        • 2017-06-10
        • 1970-01-01
        • 1970-01-01
        • 2012-10-02
        相关资源
        最近更新 更多