List(of T)和Collection(of T)有什么区别?

时间:2008-12-29 22:25:40

标签: .net list collections

我已经看到它们以很多相同的方式使用了,我担心如果我不能更好地理解这一点,我即将走上一条不可逆转的设计之路。另外,我正在使用.NET。

12 个答案:

答案 0 :(得分:60)

在C#中,有三个概念用于表示一包物体。为了增加功能,它们是:

  • 可枚举 - 无序,无法修改
  • 收藏 - 可以添加/删除项目
  • 列表 - 允许商品拥有订单(按索引访问和删除)

可枚举没有订单。您无法在集中添加或删除项目。你甚至无法获得集合中的项目数。它严格允许您一个接一个地访问集合中的每个项目。

集合是一个可修改的集合。您可以在集合中添加和删除对象,也可以获取集合中的项目数。但是仍然没有顺序,因为没有顺序:没有办法按索引访问项目,也没有办法排序。

列表是一组有序的对象。您可以对列表进行排序,按索引访问项目,按索引删除项目。

事实上,在查看这些接口时,它们是相互依赖的:

  • interface IEnumerable<T>

    • GetEnumeration<T>
  • interface ICollection<T> : IEnumerable<T>

    • Add
    • Remove
    • Clear
    • Count
  • interface IList<T> = ICollection<T>

    • Insert
    • IndexOf
    • RemoveAt

在声明变量或方法参数时,您应该选择使用

  • 的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());

如果您关心排序顺序,并且需要订单正确,请使用列表

IList<User> users = FetchUsers(db);

以图表形式:

| 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        |

List<T>中的Collection<T>System.Collections.Generic是实现这些接口的两个类;但他们并不是唯一的课程:

  • ConcurrentBag<T>是一个有序的对象包(IEnumerable<T>
  • LinkedList<T>是一个不允许您按索引访问项目的行李(ICollection);但您可以随意添加和删除集合中的项目
  • SynchronizedCollection<T>在有序集合中,您可以按索引添加/删除项目

所以你可以轻松改变:

IEnumerable<User> users = new SynchronizedCollection<User>();

SaveEveryUser(users);

TL;博士

  • 可枚举 - 访问项目,无序,不可修改
  • 收藏 - 可以修改(添加,删除,统计)
  • 列表 - 可以按索引访问

选择您需要的概念,然后使用匹配的类。

答案 1 :(得分:48)

Collection<T>IList<T>周围的可自定义包装器。虽然IList<T>未密封,但它不提供任何自定义点。 Collection<T>的方法默认委托给标准IList<T>方法,但可以轻松覆盖以执行您想要的操作。也可以在Collection<T>内汇总我认为不能用IList完成的事件。

简而言之,在事实之后扩展它会容易得多,这可能意味着更少的重构。

答案 2 :(得分:42)

List<T>旨在供应用程序代码内部使用。您应该避免编写接受或返回List<T>的公共API(请考虑使用超类或集合接口)。

Collection<T>为自定义集合提供基类(尽管可以直接使用)。

请考虑在代码中使用Collection<T>,除非您需要List<T>的特定功能。

以上只是建议。

[改编自:框架设计指南,第二版]

答案 3 :(得分:37)

List<T>是一个非常常见的容器,因为它非常通用(有许多方便的方法,如SortFind等) - 但如果你没有扩展点想要覆盖任何行为(例如,检查插入项目)。

Collection<T>是任何IList<T>的包装(默认为List<T>) - 它有扩展点(virtual方法),但没有像{{Find那样多的支持方法{1}}。由于间接,它比List<T>略慢,但不是很多。

使用LINQ,List<T>中的额外方法变得不那么重要了,因为LINQ-to-Objects无论如何都倾向于提供它们......例如First(pred)OrderBy(...)等。< / p>

答案 4 :(得分:12)

列表更快。

例如

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&lt;&gt;代码快80%。

答案 5 :(得分:11)

List表示项目顺序很重要的集合。它还支持方法s.a.排序和搜索。集合是一种更通用的数据结构,它对数据的假设较少,并且支持较少的操作方法。如果要公开自定义数据结构,则应该扩展该集合。如果您需要操作数据而不暴露数据结构,列表可能是更方便的方法。

答案 6 :(得分:4)

这是研究生的一个问题。 T的集合有点抽象;可能有一个默认实现(我不是.net / c#guy)但是一个集合将具有添加,删除,迭代等基本操作。

T的列表暗示了一些关于这些操作的细节:添加应该花费恒定的时间,删除应该花费时间与元素的数量成比例,getfirst应该是一致的时间。通常,List是一种Collection,但Collection不一定是List。

答案 7 :(得分:4)

Hanselman Speaks:“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命名空间包含可用作可重用库的对象模型中的集合的类。当属性或方法返回集合时使用这些类。”

答案 8 :(得分:4)

所有这些接口都继承自IEnumerable,您应该确保理解。该接口基本上允许您在foreach语句中使用该类(在C#中)。

  • ICollection是您列出的最基本的界面。它是一个可枚举的接口,支持Count,而且是关于它的。
  • IListICollection的所有内容,但它也支持添加和删除项目,按索引检索项目等。它是“对象列表”最常用的界面,这是模糊,我知道。
  • IQueryable是一个支持LINQ的可枚举接口。您始终可以从IList创建IQueryable并使用LINQ to Objects,但您还可以在LINQ to SQL和LINQ to Entities中找到用于延迟执行SQL语句的IQueryable
  • IDictionary在某种意义上是一种不同的动物,它是唯一键与值的映射。它也是可枚举的,你可以枚举键/值对,但除此之外它与你列出的其他目的不同。

答案 9 :(得分:4)

根据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”的“2008年12月29日22:31”帖子声称速度测试显示List(Of T)。添加比收集(Of T)更快。添加我'用Long's和String's复制。根据MSDN的说法,虽然我只比他声称的80%快了〜33%,但它应该是相反的并且是“n”次!!

答案 10 :(得分:3)

两者都实现相同的接口,因此它们的行为方式相同。也许它们在内部以不同的方式实现,但这必须进行测试。

我看到的唯一真正的区别是名称空间以及Collection<T>标有ComVisibleAttribute(false)的事实,因此COM代码无法使用它。

答案 11 :(得分:3)

除了其他asnwers之外,我还编写了通用列表和集合功能的快速概述。集合是List的有限子集:

* = present
o = partially present

Property/Method   Collection<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()                        *