List(T)和Collection(T)之间有什么区别?
我已经看到他们用了很多相同的方式,而且我担心如果我不能更好地理解这一点,我即将走上一条不可逆转的devise道路。 另外,我正在使用.NET。
Collection<T>
是一个可定制的IList<T>
包装器。 虽然IList<T>
没有密封,但没有提供任何定制点。 Collection<T>
的方法默认是委托给标准的IList<T>
方法,但是可以很容易地被覆盖来做你想做的事情。 也可以在Collection<T>
内连接事件,我不相信可以用IList来完成。
简而言之,事后扩展要容易得多,这可能意味着更less的重构。
List<T>
用于在应用程序代码内部使用。 您应该避免编写接受或返回List<T>
公共API(请改为使用超类或集合接口)。
Collection<T>
为自定义集合提供基类(尽pipe它可以直接使用)。
考虑在你的代码中使用Collection<T>
,除非有你需要的List<T>
特定function。
以上只是build议。
[改编自:框架devise指南,第二版]
在C#中,有三个用于表示一个对象的概念。 为了增加function,他们是:
- 可枚举 – 无序,不可修改
- collections – 可以添加/删除项目
- 列表 – 允许项目有订单(通过索引访问和删除)
可枚举没有顺序。 您不能添加或删除集合中的项目。 你甚至无法获得集合中的项目数量。 它严格地允许您访问集合中的每个项目,一个接一个地访问。
集合是一个可修改的集合。 您可以添加和删除集合中的对象,也可以获取集合中的项目的数量。 但还是没有秩序,因为没有秩序:没有办法通过索引来访问一个项目,也没有任何sorting的方法。
列表是一组有序的对象。 您可以对列表进行sorting,按索引访问项目,按索引删除项目。
事实上,当为这些界面查看时,他们彼此依靠:
-
interface IEnumerable<T>
-
GetEnumeration<T>
-
-
interface ICollection<T> : IEnumerable<T>
-
Add
-
Remove
-
Clear
-
Count
-
-
interface IList<T> = ICollection<T>
-
Insert
-
IndexOf
-
RemoveAt
-
在声明variables或方法参数时,应该select使用
- IEnumerable的
- ICollection的
- IList的
基于概念上你需要做的一组对象。
如果您只需要能够对列表中的每个对象执行某些操作,那么您只需要IEnumerable
:
void SaveEveryUser(IEnumerable<User> users) { for User u in users ... }
你不关心用户是否保存在一个List<T>
, Collection<T>
, Array<T>
或其他的东西里。 您只需要IEnumerable<T>
接口。
如果您需要添加,删除或统计集合中的项目,请使用集合 :
ICollection<User> users = new Collection<User>(); users.Add(new User());
如果您关心sorting顺序,并且需要该顺序是正确的,则使用列表 :
IList<User> users = FetchUsers(db);
以图表forms:
| Feature | IEnumerable<T> | ICollection<T> | IList<T> | |------------------------|----------------|----------------|----------| | Enumerating items | X | X | X | | | | | | | Adding items | | X | X | | Removing items | | X | X | | Count of items | | X | X | | | | | | | Accessing by index | | | X | | Removing by indexx | | | X | | Getting index of item | | | X |
System.Collections.Generic
中的List<T>
和Collection<T>
是实现这些接口的两个类; 但他们不是唯一的类别:
-
ConcurrentBag<T>
是一个有序的对象包(IEnumerable<T>
) -
LinkedList<T>
是一个不允许通过索引(ICollection
)访问项目的包。 但你可以任意添加和删除集合中的项目 -
SynchronizedCollection<T>
在有序集合中,您可以在其中按索引添加/删除项目
所以你可以很容易地改变:
IEnumerable<User> users = new SynchronizedCollection<User>(); SaveEveryUser(users);
TL;博士
- 可枚举 – 访问项目,无序,不可修改
- 集合 – 可以修改(添加,删除,计数)
- 列表 – 可以通过索引访问
select你需要的概念 ,然后使用匹配的类。
List<T>
是一个非常常见的容器,因为它非常多才多艺(有很多方便的方法,如Sort
, Find
等),但是如果你想覆盖任何行为(没有扩展点) , 例如)。
Collection<T>
是任何IList<T>
(默认为List<T>
)的包装 – 它具有扩展点( virtual
方法),但没有像Find
那样多的支持方法。 由于间接性,它比List<T>
稍慢,但不是太多。
使用LINQ, List<T>
的额外方法变得不那么重要,因为LINQ-to-Objects倾向于提供它们…例如First(pred)
, OrderBy(...)
等
列表代表项目顺序很重要的集合。 它也支持方法sasorting和search。 集合是一个更通用的数据结构,对数据的假设较less,也支持更less的方法来操纵它。 如果你想公开自定义数据结构,你应该扩展集合。 如果您需要操作不公开数据结构的数据,列表可能是更方便的方法。
列表更快。
做例如
private void button1_Click(object sender, EventArgs e) { Collection<long> c = new Collection<long>(); Stopwatch s = new Stopwatch(); s.Start(); for (long i = 0; i <= 10000000; i++) { c.Add(i); } s.Stop(); MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString()); List<long> l = new List<long>(); Stopwatch s2 = new Stopwatch(); s2.Start(); for (long i = 0; i <= 10000000; i++) { l.Add(i); } s2.Stop(); MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString()); }
在我的机器上List<>
几乎快了一倍。
编辑
我不明白为什么人们会这样做。 在我的工作机器和我的家用机器上,List <>代码都快了80%。
这是那些研究生问题之一。 T的集合是抽象的; 可能有一个默认的实现(我不是一个.net / c#的家伙),但一个集合将有基本的操作,如添加,删除,迭代,等等。
T列表隐含了一些关于这些操作的细节:添加应该采取一定的时间,删除应该花费与元素数量成正比的时间,首先应该是consant时间。 一般来说,一个List是一种Collection,但一个Collection不一定是一种List。
Hanselman说 :“ Collection<T>
看起来像一个列表,甚至在内部有一个List<T>
每一个单独的方法委托给内部的List<T>
,它包含一个公开List<T>
的受保护的属性。
编辑: Collection<T>
在System.Generic.Collections .NET 3.5中不存在。 如果你从.NET 2.0迁移到3.5,你将需要更改一些代码,如果你使用了很多Collection<T>
对象,除非我丢失了一些明显的东西。
编辑2: Collection<T>
现在在.NET 3.5中的System.Collections.ObjectModel命名空间。 帮助文件说:
“System.Collections.ObjectModel命名空间包含可在可重用库的对象模型中用作集合的类。当属性或方法返回集合时,请使用这些类。
所有这些接口inheritanceIEnumerable
,你应该确保你明白。 该接口基本上可以让你在foreach语句中使用该类(在C#中)。
-
ICollection
是您列出的接口中最基本的。 这是一个支持Count
的枚举接口,就是这个。 -
IList
是ICollection
一切,但它也支持添加和删除项目,通过索引检索项目等。这是“对象列表”最常用的接口,这是我知道的模糊。 -
IQueryable
是一个支持LINQ的枚举接口。 您总是可以从IList创build一个IQueryable
并使用LINQ to Objects,但是您也会发现IQueryable
用于延迟执行LINQ to SQL和LINQ to Entities中的SQL语句。 -
IDictionary
是一种不同的动物,它是唯一键值映射。 这也是可枚举的,你可以枚举键/值对,但除此之外,它的作用与您列出的其他目的不同
根据MSDN,List(Of T).Add是“一个O(n)操作”(当超过“容量”时),而Collection(Of T).Add 总是 “一个O(1)操作”。 这是可以理解的,如果List使用数组和集合链接列表实现。 但是,如果是这样的话,人们会认为Collection(Of T).Item是“一个O(n)操作”。 但是 – 不是 ! Collection(Of T).Item是“O(1)操作”,就像List(Of T).Item一样。
最重要的是,“tuinstoel”的“08年12月29日在22:31”上面声称速度testing显示List(Of T).Add比集合(Of T)快.Add我已经转载龙的和弦的。 虽然我只比自己的80%快了33%,根据MSDN,它应该是相反的,“n”倍!
两者都实现相同的接口,所以他们会performance相同的方式。 也许他们在内部的实施方式不同,但这必须经过testing。
我看到的唯一真正的区别是命名空间和Collection<T>
被ComVisibleAttribute(false)
标记的事实,所以COM代码不能使用它。
除了其他asnwers,我已经编译了通用列表和收集function的快速概述。 集合是列表的有限子集:
* =现在
o =部分存在
属性/方法集合<T> List <T>
---------------------------------------------- Add() * * AddRange() * AsReadOnly() * BinarySearch() * Capacity * Clear() * * Contains() * * ConvertAll() * CopyTo() o * Count * * Equals() * * Exists() * Find() * FindAll() * FindIndex() * FindLast() * FindLastIndex() * ForEach() * GetEnumerator() * * GetHashCode() * * GetRange() * GetType() * * IndexOf() o * Insert() * * InsertRange() * Item() * * LastIndexOf() * New() o * ReferenceEquals() * * Remove() * * RemoveAll() * RemoveAt() * * RemoveRange() * Reverse() * Sort() * ToArray() * ToString() * * TrimExcess() * TrueForAll() *