Já os vi usados de muitas maneiras semelhantes e estou preocupado em seguir um caminho no design que é irreversível se eu não entender isso melhor. Além disso, estou usando o .NET.
Já os vi usados de muitas maneiras semelhantes e estou preocupado em seguir um caminho no design que é irreversível se eu não entender isso melhor. Além disso, estou usando o .NET.
Respostas:
Collection<T>
é um invólucro personalizável IList<T>
. Embora IList<T>
não seja lacrado, não fornece pontos de personalização. Collection<T>
Os métodos de são delegados por padrão aos IList<T>
métodos padrão , mas podem ser facilmente substituídos para fazer o que você deseja. Também é possível conectar eventos dentro de um Collection<T>
que eu não acredito que poderia ser feito com um IList.
Resumindo, é muito mais fácil estendê-lo após o fato, o que poderia significar muito menos refatoração.
IList
, IList<T>
, List<T>
etc. Em suma, você não tem idéia se ele vai ser chamado. O polimorfismo corrige isso.
ObservableCollection<T>
como um exemplo onde os métodos são substituídos para notificar sobre mudanças.
Em C #, existem três conceitos para representar um pacote de objetos. Em ordem crescente de recursos, eles são:
Enumerable não tem ordem. Você não pode adicionar ou remover itens do conjunto. Você não pode nem mesmo obter uma contagem dos itens no conjunto. Ele permite que você acesse estritamente cada item do conjunto, um após o outro.
A coleção é um conjunto modificável. Você pode adicionar e remover objetos 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 objetos. Você pode classificar a lista, acessar itens por índice, remover itens por índice.
Na verdade, ao olhar para as interfaces desses, eles se baseiam um no outro:
interface IEnumerable<T>
GetEnumeration<T>
interface ICollection<T> : IEnumerable<T>
Add
Remove
Clear
Count
interface IList<T> = ICollection<T>
Insert
IndexOf
RemoveAt
Ao declarar variáveis ou parâmetros de método, você deve escolher usar
com base em conceitualmente você precisa fazer com o conjunto de objetos.
Se você só precisa ser capaz de fazer algo com todos os objetos em uma lista, você só precisa IEnumerable
:
void SaveEveryUser(IEnumerable<User> users)
{
for User u in users
...
}
Você não se importa se os usuários são mantidos em um List<T>
, Collection<T>
, Array<T>
ou qualquer outra coisa. Você só precisa da IEnumerable<T>
interface.
Se você precisar adicionar, remover ou contar os itens de um conjunto, use uma Coleção :
ICollection<User> users = new Collection<User>();
users.Add(new User());
Se você se preocupa com uma ordem de classificação e precisa que a ordem esteja correta, use uma Lista :
IList<User> users = FetchUsers(db);
Em forma de gráfico:
| 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 |
O List<T>
e Collection<T>
em System.Collections.Generic
duas classes que implementam estas interfaces; mas eles não são as únicas classes:
ConcurrentBag<T>
é uma bolsa ordenada de objetos ( IEnumerable<T>
)LinkedList<T>
é uma bolsa onde você não tem permissão para acessar itens por index ( ICollection
); mas você pode adicionar e remover arbitrariamente itens da coleçãoSynchronizedCollection<T>
em uma coleção ordenada, onde você pode adicionar / remover itens por índiceEntão você pode mudar facilmente:
IEnumerable<User> users = new SynchronizedCollection<User>();
SaveEveryUser(users);
Escolha o conceito de que precisa e, em seguida, use a classe correspondente.
ICollection<T>
e IList<T>
. Diferentes implementações concretas podem se comportar de maneira diferente. Por exemplo, se você acessar um List<T>
por meio de sua IEnumerable<T>
interface, não terá como adicionar, remover, classificar ou contar itens na lista.
List<T>
destina-se ao uso interno no código do aplicativo. Você deve evitar escrever APIs públicas que aceitam ou retornam List<T>
(em vez disso, considere usar uma superclasse ou uma interface de coleção).
Collection<T>
serve uma classe base para coleções personalizadas (embora possa ser usada diretamente).
Considere usar Collection<T>
em seu código, a menos que haja recursos específicos de List<T>
que você precisa.
Os itens acima são apenas recomendações.
[Adaptado de: Framework Design Guidelines, Second Edition]
Dictionary<string, List<string>>
retornar List<string>
está bem, uma vez que o estado do dicionário apenas encapsula o identidades das listas nele, ao invés de seu conteúdo.
List<T>
é um contêiner muito comumente visto, porque é muito versátil (com muitos métodos úteis como Sort
, Find
etc) - mas não tem pontos de extensão se você quiser sobrescrever qualquer um dos comportamentos (verifique os itens na inserção, por exemplo).
Collection<T>
é um wrapper em torno de qualquer IList<T>
(assumindo como padrão List<T>
) - ele tem os pontos de extensão ( virtual
métodos), mas não tantos métodos de suporte como Find
. Por causa da indireção, é um pouco mais lento do que List<T>
, mas não muito.
Com LINQ, os métodos extras em List<T>
tornam-se menos importante, já que LINQ-to-Objects tende a fornecê-los de qualquer maneira ... por exemplo First(pred)
, OrderBy(...)
, etc.
Listar é mais rápido.
Faça por exemplo
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());
}
na minha máquina List<>
é quase duas vezes mais rápido.
Editar
Não consigo entender por que as pessoas estão rejeitando isso. Tanto em minha máquina de trabalho quanto em minha máquina doméstica, o código List <> é 80% mais rápido.
A lista representa uma coleção em que a ordem dos itens é importante. Ele também suporta métodos de classificaçã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 métodos para manipulá-los. Se você deseja expor uma estrutura de dados customizada, provavelmente deve estender a coleção. Se você precisa manipular dados sem expor a estrutura de dados, uma lista é provavelmente o caminho mais conveniente.
Esta é uma daquelas questões da pós-graduação. Uma coleção de T é meio abstrata; pode haver uma implementação padrão (não sou um cara .net / c #), mas uma coleção terá operações básicas como adicionar, remover, iterar e assim por diante.
A lista de T implica alguns detalhes sobre essas operações: add deve levar um tempo constante, remove deve levar um tempo proporcional ao número de elementos, getfirst deve ser um tempo constante. Em geral, uma lista é um tipo de coleção, mas uma coleção não é necessariamente um tipo de lista.
Hanselman fala : " Collection<T>
parece uma lista, e tem até um List<T>
interno. CADA método único delega para o interno List<T>
. Inclui uma propriedade protegida que expõe o List<T>
."
EDIT: Collection<T>
não existe em System.Generic.Collections .NET 3.5. Se você migrar do .NET 2.0 para 3.5, você precisará alterar algum código se estiver usando muitoCollection<T>
objetos, a menos que esteja faltando algo óbvio ...
EDIT 2: Collection<T>
agora está no namespace System.Collections.ObjectModel no .NET 3.5. O arquivo de ajuda diz o seguinte:
"O namespace System.Collections.ObjectModel contém classes que podem ser usadas como coleções no modelo de objeto de uma biblioteca reutilizável. Use essas classes quando propriedades ou métodos retornarem coleções."
Todas essas interfaces são herdadas de IEnumerable
, o que você deve ter certeza de entender. Essa interface basicamente permite que você use a classe em uma instrução foreach (em C #).
ICollection
é a mais básica das interfaces que você listou. É uma interface enumerável que oferece suporte a um Count
e é tudo.IList
é tudo o que ICollection
existe, mas também suporta adicionar e remover itens, recuperar itens por índice, etc. É a interface mais comumente usada para "listas de objetos", o que eu sei é vago.IQueryable
é uma interface enumerável que oferece suporte a LINQ. Você sempre pode criar um IQueryable
de um IList e usar LINQ to Objects, mas também pode ser IQueryable
usado para execução adiada de instruções SQL em 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 no sentido de que você pode enumerar os pares chave / valor, mas, caso contrário, serve a um propósito diferente dos outros que você listouDe acordo com o MSDN, List (Of T) .Add é "uma operação O (n)" (quando "Capacity" é excedida), enquanto Collection (Of T) .Add é sempre "uma operação O (1)". Isso seria compreensível se List fosse implementado usando um Array e Collection a Linked List. No entanto, se fosse esse o caso, seria de se esperar que Collection (Of T) .Item fosse "uma operação O (n)". Mas - é - não !?! Collection (Of T) .Item é "uma operação O (1)" assim como List (Of T) .Item.
Além disso, "tuinstoel" s "Dec 29 '08 at 22:31" post acima afirma que os testes de velocidade mostram List (Of T). Adicione para ser mais rápido que Collection (Of T) .Add que reproduzi com Long's e String's. Embora eu só tenha ficado ~ 33% mais rápido contra seus 80% reivindicados, de acordo com o MSDN, deveria ter sido o oposto e "n" vezes!?!
Ambos implementam as mesmas interfaces, portanto, 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<T>
está marcado com ComVisibleAttribute(false)
, portanto, o código COM não pode usá-lo.
Além de outras perguntas, eu compilei uma visão geral rápida de listas genéricas e recursos de coleção. A coleção é um subconjunto limitado da Lista:
* = presente
o = parcialmente presente
Coleção de Propriedade / Método < T > Lista < 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() *