我已经从事Windows的C#和ASP.net MVC开发工作了一段时间。但是我在一些方面仍然不清楚。我试图了解使用和互换相似种类的通用集合接口之间的基本区别和性能问题。
之间有什么根本区别IEnumerable<T>
,ICollection<T>
,List<T>(Class)
?
我似乎在使用和交换它们时在我的应用程序中没有发现任何问题。另外,还有其他类似的通用集合可以与这三个集合互换吗?
我已经从事Windows的C#和ASP.net MVC开发工作了一段时间。但是我在一些方面仍然不清楚。我试图了解使用和互换相似种类的通用集合接口之间的基本区别和性能问题。
之间有什么根本区别IEnumerable<T>
,ICollection<T>
,List<T>(Class)
?
我似乎在使用和交换它们时在我的应用程序中没有发现任何问题。另外,还有其他类似的通用集合可以与这三个集合互换吗?
Answers:
List <T>是一个类,并且实现ICollection <T>和IEnumerable <T>接口。同样,ICollection <T>扩展了IEnumerable <T>接口。它们是不可互换的,至少从所有角度来看都是不可互换的。
如果您具有List <T>,则可以确保此对象实现ICollection <T>和IEnumerable <T>接口需要实现的方法和属性。编译器知道它,并且可以将它们“隐式”转换为ICollection <T>或IEnumerable <T>隐式。但是,如果您有ICollection <T>,则必须先在代码中显式检查它是否是List <T>或其他内容,也许是Dictionary <T>(其中T是KeyValuePair),然后再将其强制转换为您的内容欲望。
您知道ICollection扩展了IEnumerable,因此您可以将其转换为IEnumerable。但是,如果只有IEnumerable,则不能保证它是列表。可能是,但是可能是其他。例如,如果您确实尝试将List <T>强制转换为Dictionary <T>,则应该期待一个无效的强制转换异常。
因此它们不是“可互换的”。
另外,还有很多通用接口,请查看在System.Collections.Generic命名空间中可以找到的内容。
编辑:关于您的评论,如果您使用List <T>或它实现的接口之一,则绝对不会降低性能。您仍然需要创建一个新对象,签出以下代码:
List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;
list,myColl和myEnum都指向同一对象。无论您将其声明为列表,ICollection还是IEnumerable,我仍然需要程序创建列表。我可以这样写:
ICollection<T> myColl = new List<T>();
MYCOLL,在运行时仍然是一个列表。
但是,这是最重要的一点…… 为了减少耦合并提高可维护性,您应该始终使用对您来说尽可能最小的分母来声明变量和方法参数,无论是接口,抽象类还是具体类。
想象一下,“ PerformOperation”方法唯一需要的是枚举元素,进行一些工作并退出,在这种情况下,您不需要List <T>中可用的一百种方法,只需要IEnumerable <T中可用的方法即可。 >,因此以下情况适用:
public void PerformOperation(IEnumerable<T> myEnumeration) { ... }
这样,您和其他开发人员便知道可以将实现IEnumerable <T>接口的类的任何对象赋予该方法。它可能是列表,字典或其他开发人员编写的自定义集合类。
相反,如果您明确指定需要一个具体的List <T>(尽管在现实生活中很少见,但仍然可能发生),那么您和其他开发人员都知道它必须是List或另一个继承的具体类来自列表。
IList
而不是List
在方法声明中使用。
List<>
特定的功能,例如.AddRange()
。在IList<>
不公开这一点。
看看ICollection和IEnumerable的MSDN页面。
用非常抽象的术语来说,这就是我对这些类型的构想。
IEnumerable是可以枚举的任何东西-即,迭代。它不一定意味着“集合”;例如,一个IQueryable实现IEnumerable,它不是一个集合,而是可以查询返回对象的东西。要实现IEnumerable,只需要在查询对象时就可以返回对象。我可能会说我有今天要执行的无数任务(它不是清单,因为我没有写下来或拟定它,但是我可以告诉你我现在要做什么,并且如果您问“然后呢?”,我可以告诉您以下任务)。
ICollection比IEnumerable更具体。一个关键的区别是,一个集合知道它包含多少个项目。要计算一个Enumerable中有多少个项目,您可以有效地遍历并计数:
我:伙计们,你们每个人都有几件物品?
不可思议:我真的不知道。好吧,这是一件。我还有一个,所以是两个。还有一个,所以是三个...另一个是...好,所以是2382。没有其他项目了,所以我有了2382。不要再问我,因为我将不得不再次检查它们。
收藏品:我有2382件物品。我已经知道了
集合通常是一种已经知道所有元素在哪里的东西,并且在您要寻找它们时不必去寻找或生成它们。它比枚举更具体。
在我看来,Enumerable和Collection之间的差异远大于Collection和List之间的差异。实际上,我在努力考虑Collection和List之间的实际区别,但是我相信List提供了更好的搜索和排序方法。
其他类型的Collection包括Queue
和Stack
,以及Dictionary
。
这些类型的名称非常有用-您可以将队列和堆栈视为它们在现实世界中的对应对象,并考虑与List之间可能存在的差异。
List
是一个ICollection
,而是一个ICollection
并不总是一个List
(Queue
,Stack
,Dictionary
,...)
Queue<int> queue = (Queue<int>)list;
会InvalidCastException
在list
不为时抛出一个Queue<int>
。队列和列表之间的差异超出了此问题的范围。
可查询的:
直到真正遍历项目才执行查询,可能是通过执行.ToList()
IEnumerable:
前向项目列表。不通过项目0-3,您将无法获得“项目4”。只读列表,您不能添加或删除列表。仍可能使用延迟执行。
IList:
随机访问完全在内存中的完整列表,支持添加和删除
ICollection:
在IEnumerable和IList之间。什么是“最佳”取决于您的要求。通常,如果只想显示项目,则IEnumerable就足够了。至少总是使用通用变量。