Qual é a diferença entre List (of T) e Collection (of T)?

Eu os vi usados ​​da mesma maneira, e estou preocupada que estou prestes a seguir um caminho no design que é irreversível se eu não entender isso melhor. Além disso, estou usando o .NET.

    Collection é um wrapper personalizável em torno de IList . Enquanto o IList não está lacrado, ele não fornece nenhum ponto de personalização. Collection methods da Collection são, por padrão, delegates aos methods IList padrão, mas podem ser facilmente substituídos para fazer o que você deseja. Também é possível conectar events dentro de uma Collection que eu não acredito que possa ser feito com um IList.

    Em suma, é muito mais fácil estendê-lo após o fato, o que poderia significar muito menos refatoração.

    Em C #, existem três conceitos para representar uma bolsa de objects. Em ordem crescente de resources, eles são:

    • Enumerável – não ordenado, não modificável
    • Coleção – pode adicionar / remover itens
    • Lista – permite que itens tenham um pedido (acessando e removendo por índice)

    Enumerável não tem ordem. Você não pode adicionar ou remover itens do conjunto. Você não pode nem obter uma contagem de itens no conjunto. Ele permite que você acesse cada item do conjunto, um após o outro.

    A coleção é um conjunto modificável. Você pode adicionar e remover objects do conjunto, você também pode obter a contagem de itens no conjunto. Mas ainda não há ordem, e porque não há ordem: não há como acessar um item por índice, nem há como classificar.

    Lista é um conjunto ordenado de objects. Você pode classificar a lista, acessar itens por índice, remover itens por índice.

    De fato, ao olhar as interfaces para estes, eles constroem um no outro:

    • interface IEnumerable

      • GetEnumeration
    • interface ICollection : IEnumerable

      • Add
      • Remove
      • Clear
      • Count
    • interface IList = ICollection

      • Insert
      • IndexOf
      • RemoveAt

    Ao declarar variables, ou parâmetros de método, você deve optar por usar

    • IEnumerable
    • ICollection
    • IList

    baseado conceitualmente, você precisa fazer com o conjunto de objects.

    Se você só precisa fazer algo para cada object em uma lista, então você só precisa de IEnumerable :

     void SaveEveryUser(IEnumerable users) { for User u in users ... } 

    Você não se importa se os Usuários são mantidos em uma List , Collection , Array ou qualquer outra coisa. Você só precisa da IEnumerable .

    Se você precisar adicionar, remover ou contar os itens em um conjunto, use uma Coleção :

     ICollection users = new Collection(); users.Add(new User()); 

    Se você se preocupa com uma ordem de sorting e precisa que a ordem esteja correta, use uma Lista :

     IList users = FetchUsers(db); 

    Em forma de gráfico:

     | Feature | IEnumerable | ICollection | IList | |------------------------|----------------|----------------|----------| | 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 | 

    O List e Collection no System.Collections.Generic são duas classs que implementam essas interfaces; mas eles não são as únicas classs:

    • ConcurrentBag é uma mala ordenada de objects ( IEnumerable )
    • LinkedList é um saco onde você não tem permissão para acessar itens por índice ( ICollection ); mas você pode adicionar e remover arbitrariamente itens da coleção
    • SynchronizedCollection em uma coleção ordenada, onde você pode adicionar / remover itens por índice

    Então você pode facilmente mudar:

     IEnumerable users = new SynchronizedCollection(); SaveEveryUser(users); 

    tl; dr

    • Enumerável – itens de access, não ordenados, não modificáveis
    • Coleção – pode ser modificado (adicionar, excluir, contar)
    • Lista – pode acessar por índice

    Escolha o conceito que você precisa e use a class correspondente.

    List destina-se ao uso interno dentro do código do aplicativo. Você deve evitar escrever APIs públicas que aceitem ou retornem List (considere o uso de uma superclass ou uma interface de coleta).

    Collection serve uma class base para collections personalizadas (embora possa ser usada diretamente).

    Considere o uso de Collection em seu código, a menos que haja resources específicos de List que você precisa.

    Os acima são apenas recomendações.

    [Adaptado de: Framework Design Guidelines, Second Edition]

    List é um container comumente visto, porque é muito versátil (com muitos methods úteis como Sort , Find , etc) – mas não possui pontos de extensão se você quiser sobrescrever qualquer um dos comportamentos (verifique itens no insert , por exemplo).

    Collection é um wrapper em torno de qualquer IList (padronizado para List ) – ele possui os pontos de extensão (methods virtual ), mas não tantos methods de suporte como o Find . Por causa da indireção, é um pouco mais lento que List , mas não muito.

    Com o LINQ, os methods extras em List se tornam menos importantes, já que o LINQ-to-Objects tende a fornecê-los de qualquer maneira … por exemplo, First(pred) , OrderBy(...) , etc.

    Lista é mais rápida.

    Por exemplo

     private void button1_Click(object sender, EventArgs e) { Collection c = new Collection(); 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 l = new List(); Stopwatch s2 = new Stopwatch(); s2.Start(); for (long i = 0; i < = 10000000; i++) { l.Add(i); } s2.Stop(); MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString()); } 

    na minha máquina List<> é quase duas vezes mais rápido.

    Editar

    Não consigo entender por que as pessoas estão fazendo isso. Tanto na minha máquina de trabalho quanto na minha máquina doméstica, o código List <> é 80% mais rápido.

    List representa uma coleção em que a ordem dos itens é importante. Ele também suporta methods na ordenação e pesquisa. A coleção é uma estrutura de dados mais geral que faz menos suposições sobre os dados e também suporta menos methods para manipulá-los. Se você quiser expor uma estrutura de dados personalizada, provavelmente deverá estender a coleção. Se você precisar manipular dados sem expor a estrutura de dados, uma lista é provavelmente a maneira mais conveniente de ir.

    Essa é uma daquelas perguntas da pós-graduação. Uma coleção de T é uma espécie de resumo; pode haver uma implementação padrão (eu não sou um cara .net / c #), mas uma coleção terá operações básicas como adicionar, remover, iterar e assim por diante.

    Lista de T implica algumas especificidades sobre estas operações: add deve levar tempo constante, remove deve levar tempo proporcional ao número de elementos, get primeiro deve ser o tempo consant. Em geral, uma lista é um tipo de coleção, mas uma coleção não é necessariamente um tipo de lista.

    Hanselman fala : ” Collection parece com uma lista, e ela ainda tem uma List internamente. Cada método único delega na List interna List . Ele inclui uma propriedade protegida que expõe a List .”

    EDIT: Collection não existe no System.Generic.Collections .NET 3.5. Se você migrar do .NET 2.0 para o 3.5, precisará alterar algum código se estiver usando muitos objects Collection , a menos que esteja faltando algo óbvio …

    EDIT 2: Collection está agora no namespace System.Collections.ObjectModel no .NET 3.5. O arquivo de ajuda diz isto:

    “O namespace System.Collections.ObjectModel contém classs que podem ser usadas como collections no modelo de object de uma biblioteca reutilizável. Use essas classs quando propriedades ou methods retornarem collections.”

    Todas essas interfaces herdam de IEnumerable , o que você deve entender. Essa interface basicamente permite usar a class em uma instrução foreach (em C #).

    • ICollection é a mais básica das interfaces listadas. É uma interface enumerável que suporta um Count e é sobre isso.
    • IList é tudo que ICollection é, mas também suporta adicionar e remover itens, recuperar itens por índice, etc. É a interface mais comumente usada para “listas de objects”, o que é vago eu sei.
    • IQueryable é uma interface enumerável que suporta o LINQ. Você sempre pode criar um IQueryable de um IList e usar o LINQ para objects, mas você também encontrará IQueryable usado para execução adiada de instruções SQL no LINQ to SQL e LINQ to Entities.
    • IDictionary é um animal diferente no sentido de que é um mapeamento de chaves exclusivas para valores. Também é enumerável que você pode enumerar os pares de chave / valor, mas, caso contrário, ele serve a um propósito diferente dos outros que você listou

    De acordo com o MSDN, List (Of T) .Add é “uma operação O (n)” (quando “Capacidade” é excedida) enquanto Collection (Of T) .Add é sempre “uma operação O (1)”. Isso seria compreensível se a lista fosse implementada usando uma matriz e uma coleção de uma linked list. No entanto, se esse fosse o caso, seria de se esperar que Collection (Of T) .Item fosse “uma operação O (n)”. Mas – não é! Coleção (Of T) .Item é “uma operação O (1)” apenas como List (Of T) .Item.

    Além disso, “tuinstoel” “29 de dezembro de 2008 às 22:31” post acima dos testes de velocidade de reivindicações mostram List (Of T) .Adicione ser mais rápido que Collection (Of T) .Adicione que eu reproduzi com Long e String. Embora eu tenha apenas ~ 33% mais rápido do que o seu alegado 80%, de acordo com o MSDN, deveria ter sido o oposto e por “n” vezes!?!

    Ambos implementam as mesmas interfaces, então eles se comportarão da mesma maneira. Talvez eles sejam implementados de forma diferente internamente, mas isso teria que ser testado.

    As únicas diferenças reais que vejo são os namespaces e o fato de que Collection está marcado com ComVisibleAttribute(false) , portanto, o código COM não pode usá-lo.

    Além de outras asnwers, eu compilei uma rápida visão geral dos resources genéricos de lista e coleta. A coleta é um subconjunto limitado da lista:

     * = presente
     o = parcialmente presente
    
     Coleção de propriedade / método  List 
     ---------------------------------------------- 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() *