Qual é a diferença entre ArrayList
eList<>
em c #?
É apenas que List<>
tem um tipo enquanto ArrayList
não?
List<>
em geral, enquanto que uma pergunta sobre List<object>
especificamente
Qual é a diferença entre ArrayList
eList<>
em c #?
É apenas que List<>
tem um tipo enquanto ArrayList
não?
List<>
em geral, enquanto que uma pergunta sobre List<object>
especificamente
Respostas:
Sim, praticamente. List<T>
é uma classe genérica. Ele suporta o armazenamento de valores de um tipo específico sem conversão para ou de object
(o que teria incorrido em sobrecarga de boxe / unboxing quando T
é um tipo de valor no ArrayList
caso). ArrayList
simplesmente armazena object
referências. Como uma coleção genérica, List<T>
implementa o genérico IEnumerable<T>
de interface e pode ser usado facilmente em LINQ (sem necessidade de qualquer Cast
ou de OfType
chamada).
ArrayList
pertence aos dias em que o C # não tinha genéricos. Está obsoleto em favor de List<T>
. Você não deve usar um ArrayList
novo código que tenha como alvo .NET> = 2.0, a menos que tenha que fazer interface com uma API antiga que a usa.
ArrayList
no tempo de execução. Estaticamente, porém, será necessário um elenco ArrayList
.
Usando List<T>
você pode evitar erros de conversão. É muito útil evitar um tempo de execução erro de conversão de execução.
Exemplo:
Aqui (usando ArrayList
) você pode compilar esse código, mas você verá um erro de execução posteriormente.
ArrayList array1 = new ArrayList();
array1.Add(1);
array1.Add("Pony"); //No error at compile process
int total = 0;
foreach (int num in array1)
{
total += num; //-->Runtime Error
}
Se você usar List
, evite estes erros:
List<int> list1 = new List<int>();
list1.Add(1);
//list1.Add("Pony"); //<-- Error at compile process
int total = 0;
foreach (int num in list1 )
{
total += num;
}
Referência: MSDN
Para adicionar aos pontos acima. O uso ArrayList
no sistema operacional de 64 bits requer 2x memória do que o uso no sistema operacional de 32 bits. Enquanto isso, a lista genérica List<T>
usará muito pouca memória que aArrayList
.
por exemplo, se usarmos um ArrayList
de 19 MB em 32 bits, serão necessários 39 MB nos 64 bits. Mas se você tiver uma lista genéricaList<int>
de 8 MB em 32 bits, serão necessários apenas 8,1 MB em 64 bits, que é uma diferença gritante de 481% quando comparado ao ArrayList.
Fonte: lista ArrayList vs. genérica para tipos primitivos e 64 bits
Outra diferença a ser adicionada é com relação à sincronização de threads.
ArrayList
fornece alguma segurança de thread através da propriedade Synchronized, que retorna um wrapper seguro de thread em torno da coleção. O wrapper funciona bloqueando a coleção inteira em todas as operações de adição ou remoção. Portanto, cada encadeamento que está tentando acessar a coleção deve aguardar sua vez de bloquear o único bloqueio. Isso não é escalável e pode causar degradação significativa no desempenho de grandes coleções.
List<T>
não fornece nenhuma sincronização de encadeamento; o código do usuário deve fornecer toda a sincronização quando itens são adicionados ou removidos em vários threads simultaneamente.
Mais informações aqui Sincronização de threads no .Net Framework
ArrayList
se puder ser evitado, mas esse é um motivo bobo. O wrapper é totalmente opcional, afinal; se você não precisar de bloqueio ou se precisar de mais controle granular, não use o wrapper.
Resposta simples é,
ArrayList arrayList = new ArrayList();
List<int> list = new List<int>();
arrayList.Add(1);
arrayList.Add("String");
arrayList.Add(new object());
list.Add(1);
list.Add("String"); // Compile-time Error
list.Add(new object()); // Compile-time Error
Leia o documento oficial da Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
Nota : Você deve conhecer os Genéricos antes de entender a diferença: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
é a coleta de tipos diferentes de dados, enquanto List<>
a coleta de tipos semelhantes de suas próprias dependências.
ArrayList
não são do tipo seguro, enquanto List<T>
são do tipo seguro. Simples :).
O desempenho já foi mencionado em várias respostas como um fator diferenciador, mas para abordar a questão “ Quanto mais lento é o ArrayList
? ”E“ Por que é mais lento no geral?”, Dê uma olhada abaixo.
Sempre que tipos de valor são usados como elementos, o desempenho diminui drasticamente ArrayList
. Considere o caso de simplesmente adicionar elementos. Devido ao boxe - como ArrayList
o Add adiciona apenas object
parâmetros - o Garbage Collector é acionado para executar muito mais trabalho do que comList<T>
.
Quanto é a diferença horária? Pelo menos várias vezes mais lento que com List<T>
. Basta dar uma olhada no que acontece com o código adicionando 10 mil int valores a um ArrayList
vs List<T>
:
Essa é uma diferença de tempo de execução de 5x na coluna "Média", destacada em amarelo. Observe também a diferença no número de coletas de lixo feitas para cada uma, destacadas em vermelho (sem GCs / 1000 execuções).
O uso de um criador de perfil para ver o que está acontecendo rapidamente mostra que a maior parte do tempo é gasta na criação de GCs , em vez de realmente adicionar elementos. As barras marrons abaixo representam o bloqueio da atividade do Garbage Collector:
Escrevi uma análise detalhada do que se passa com o ArrayList
cenário acima aqui https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .
Resultados semelhantes estão em "CLR via C #", de Jeffrey Richter. Do capítulo 12 (Genéricos):
[…] Ao compilar e executar uma compilação de versão (com otimizações ativadas) deste programa no meu computador, recebo a seguinte saída.
00: 00: 01.6246959 (GCs = 6) Lista <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayList of Int32
00: 00: 02.5427847 (GCs = 4) Lista <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList de StringA saída aqui mostra que o uso do algoritmo List genérico com o tipo Int32 é muito mais rápido do que o uso do algoritmo ArrayList não genérico com o Int32. De fato, a diferença é fenomenal: 1,6 segundos versus quase 11 segundos. Isso é ~ 7 vezes mais rápido ! Além disso, o uso de um tipo de valor (Int32) com ArrayList causa muitas operações de boxe, o que resulta em 390 coletas de lixo. Enquanto isso, o algoritmo List exigia 6 coletas de lixo.
Eu acho que as diferenças entre ArrayList
e List<T>
são:
List<T>
, onde T é do tipo valor é mais rápido que ArrayList
. Isso ocorre porque List<T>
evita boxe / unboxing (onde T é do tipo valor).ArrayList
usadas apenas para compatibilidade com versões anteriores. (não é uma diferença real, mas acho que é uma nota importante).ArrayList
seguidaList<T>
ArrayList
tem IsSynchronized
propriedade. Portanto, é fácil criar e usar sincronizado ArrayList
. Não encontrei IsSynchronized
propriedades para List<T>
. Lembre-se também de que esse tipo de sincronização é relativamente ineficiente, msdn ):
var arraylist = new ArrayList();
var arrayListSyncronized = ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");
Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");
var list = new List<object>();
var listSyncronized = ArrayList.Synchronized(list);
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayList
possui ArrayList.SyncRoot
propriedade que pode ser usada para sincronização ( msdn ). List<T>
não possui SyncRoot
propriedade, portanto, na construção a seguir, você precisará usar algum objeto se usar List<T>
:
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
Conforme mencionado na documentação do .NET Framework
Não recomendamos que você use a
ArrayList
classe para novos desenvolvimentos. Em vez disso, recomendamos que você use aList<T>
classe genérica . AArrayList
classe foi projetada para armazenar coleções heterogêneas de objetos. No entanto, nem sempre oferece o melhor desempenho. Em vez disso, recomendamos o seguinte:
- Para uma coleção heterogênea de objetos, use o tipo
List<Object>
(em C #) ouList(Of Object)
(no Visual Basic).- Para uma coleção homogênea de objetos, use a
List<T>
classe
Consulte também Coleções não genéricas não devem ser usadas
Usando a "Lista", você pode evitar erros de conversão. É muito útil evitar um erro de conversão de tempo de execução.
Exemplo:
Aqui (usando ArrayList) você pode compilar esse código, mas você verá um erro de execução posteriormente.
// Create a new ArrayList
System.Collections.ArrayList mixedList = new System.Collections.ArrayList();
// Add some numbers to the list
mixedList.Add(7);
mixedList.Add(21);
// Add some strings to the list
mixedList.Add("Hello");
mixedList.Add("This is going to be a problem");
System.Collections.ArrayList intList = new System.Collections.ArrayList();
System.Collections.ArrayList strList = new System.Collections.ArrayList();
foreach (object obj in mixedList)
{
if (obj.GetType().Equals(typeof(int)))
{
intList.Add(obj);
}
else if (obj.GetType().Equals(typeof(string)))
{
strList.Add(obj);
}
else
{
// error.
}
}
Para mim, é tudo uma questão de conhecer seus dados. Se eu continuar expandindo meu código com base na eficiência, teria que escolher a opção Lista como uma maneira de decifrar meus dados sem a etapa desnecessária de sempre me perguntar sobre tipos, especialmente 'Tipos personalizados'. Se a máquina entende a diferença e pode determinar com que tipo de dados estou realmente lidando, por que devo atrapalhar e perder tempo passando pelas variações das determinações "SE ENTÃO MAIS"? Minha filosofia é deixar a máquina trabalhar para mim em vez de trabalhar na máquina? Conhecer as diferenças exclusivas de diferentes comandos de código de objeto ajuda bastante a tornar seu código tão eficiente.
Tom Johnson (uma entrada ... uma saída)