É uma pergunta próxima, mas acho que não exatamente duplicada. Esta pergunta sobre List<>em geral, enquanto que uma pergunta sobre List<object>especificamente
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 ArrayListcaso). ArrayListsimplesmente armazena objectreferê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 Castou de OfTypechamada).
ArrayListpertence aos dias em que o C # não tinha genéricos. Está obsoleto em favor de List<T>. Você não deve usar um ArrayListnovo código que tenha como alvo .NET> = 2.0, a menos que tenha que fazer interface com uma API antiga que a usa.
Você se importaria de explicar por que usou "boxe" e não "fundição"? Que boxe acontece aqui? Os objetos são alocados / desalocados?
Benjamin Gruenbaum 7/11
2
@BenjaminGruenbaum Você está certo de que o elenco seria mais geral. Dito isto, a verdadeira diferença no tempo de execução é quando você está lidando com tipos de valor (que é o que eu assumi quando escrevi "boxe"). Para tipos de referência, o comportamento é efetivamente o mesmo que ArrayListno tempo de execução. Estaticamente, porém, será necessário um elenco ArrayList.
Mehrdad Afshari
Eu queria saber se o framework deve restringir T para ser do tipo "objeto", pois ArrayList implicitamente permite isso.
rajibdotnet
Sobre a descontinuação de coleções não
tipadas
@ Ant_222, esse blog foi escrito há quase 15 anos. Acho que as evidências da última década mostraram que os genéricos não são prejudiciais. :)
Scott Adams
101
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 =newArrayList();
array1.Add(1);
array1.Add("Pony");//No error at compile processint total =0;foreach(int num in array1){
total += num;//-->Runtime Error}
Se você usar List, evite estes erros:
List<int> list1 =newList<int>();
list1.Add(1);//list1.Add("Pony"); //<-- Error at compile processint total =0;foreach(int num in list1 ){
total += num;}
Você pode verificar o tipo ao extrair do ArrayList para evitar erros de conversão. Atualmente, as pessoas usam objetos, tornando ArrayList não mais necessário.
Comute
1
i +1 à justificação, mas você ainda pode fazer se (num é int) {} à sua lista de matriz para erros a evitar
Mina Gabriel
Evite erros de fundição e sobrecarga de boxe. Praticamente os motivos dos genéricos em geral.
Marsze # 24/18
26
Para adicionar aos pontos acima. O uso ArrayListno 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 ArrayListde 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.
isso é verdadeiro apenas para armazenar tipos de valor, não tipos de referência. a diferença se deve ao fato de uma lista de matriz poder conter apenas ponteiros e os próprios dados precisam ser armazenados em outro local. Por outro lado, os tipos de valor podem ser armazenados diretamente em uma lista.
Rasmus Damgaard Nielsen
19
Outra diferença a ser adicionada é com relação à sincronização de threads.
ArrayListfornece 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.
Não estou dizendo que você deve usar ArrayListse 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.
Thorarin
1
Se você deseja segurança de thread, sugiro olhar para o namespace System.Collections.Concurrent antes de considerar ArrayList.
Ykok
15
Resposta simples é,
ArrayList não é genérico
É um tipo de objeto, para que você possa armazenar qualquer tipo de dados nele.
Você pode armazenar quaisquer valores (tipo de valor ou tipo de referência), como string, int, funcionário e objeto no ArrayList. (Nota e)
Boxe e Unboxing vai acontecer.
Não é seguro.
É mais velho.
A lista é genérica
É um Tipo de Tipo, para que você possa especificar o T no tempo de execução.
Você pode armazenar um único valor do Tipo T (sequência ou int ou funcionário ou objeto) com base na declaração. (Nota ou)
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 ArrayListo Add adiciona apenas objectparâ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 ArrayListvs 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:
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 String
A 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 ArrayListe 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).
Muitas fontes dizem - geralmente ArrayListusadas apenas para compatibilidade com versões anteriores. (não é uma diferença real, mas acho que é uma nota importante).
A reflexão é mais fácil com nongeneric ArrayListseguidaList<T>
ArrayListtem IsSynchronizedpropriedade. Portanto, é fácil criar e usar sincronizado ArrayList. Não encontrei IsSynchronizedpropriedades para List<T>. Lembre-se também de que esse tipo de sincronização é relativamente ineficiente, msdn ):
var arraylist =newArrayList();var arrayListSyncronized =ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");varlist=newList<object>();var listSyncronized =ArrayList.Synchronized(list);Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such propConsole.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayListpossui ArrayList.SyncRootpropriedade que pode ser usada para sincronização ( msdn ). List<T>não possui SyncRootpropriedade, portanto, na construção a seguir, você precisará usar algum objeto se usar List<T>:
ArrayList myCollection =newArrayList();lock(myCollection.SyncRoot)// ofcourse you can use another object for this goal{foreach(object item in myCollection){// ...}}
Não recomendamos que você use a ArrayListclasse para novos desenvolvimentos. Em vez disso, recomendamos que você use a List<T>
classe genérica . A ArrayListclasse 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 #) ou List(Of Object)(no Visual Basic).
Para uma coleção homogênea de objetos, use a List<T>classe
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 ArrayListSystem.Collections.ArrayList mixedList =newSystem.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 =newSystem.Collections.ArrayList();System.Collections.ArrayList strList =newSystem.Collections.ArrayList();foreach(object obj in mixedList){if(obj.GetType().Equals(typeof(int))){
intList.Add(obj);}elseif(obj.GetType().Equals(typeof(string))){
strList.Add(obj);}else{// error.}}
O que isso acrescenta além da resposta que os termas deram três anos antes? Possui quase o mesmo texto, literalmente, sem vincular à fonte, sem formatar corretamente, etc. #
Douglas Zare
-3
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.
List<>
em geral, enquanto que uma pergunta sobreList<object>
especificamenteRespostas:
Sim, praticamente.
List<T>
é uma classe genérica. Ele suporta o armazenamento de valores de um tipo específico sem conversão para ou deobject
(o que teria incorrido em sobrecarga de boxe / unboxing quandoT
é um tipo de valor noArrayList
caso).ArrayList
simplesmente armazenaobject
referências. Como uma coleção genérica,List<T>
implementa o genéricoIEnumerable<T>
de interface e pode ser usado facilmente em LINQ (sem necessidade de qualquerCast
ou deOfType
chamada).ArrayList
pertence aos dias em que o C # não tinha genéricos. Está obsoleto em favor deList<T>
. Você não deve usar umArrayList
novo código que tenha como alvo .NET> = 2.0, a menos que tenha que fazer interface com uma API antiga que a usa.fonte
ArrayList
no tempo de execução. Estaticamente, porém, será necessário um elencoArrayList
.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.Se você usar
List
, evite estes erros:Referência: MSDN
fonte
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éricaList<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
fonte
Outra diferença a ser adicionada é com relação à sincronização de threads.
Mais informações aqui Sincronização de threads no .Net Framework
fonte
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 não é genérico
A lista é genérica
Exemplo:
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/
fonte
ArrayList
é a coleta de tipos diferentes de dados, enquantoList<>
a coleta de tipos semelhantes de suas próprias dependências.fonte
ArrayList
não são do tipo seguro, enquantoList<T>
são do tipo seguro. Simples :).fonte
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 - comoArrayList
o Add adiciona apenasobject
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 umArrayList
vsList<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):
fonte
Eu acho que as diferenças entre
ArrayList
eList<T>
são:List<T>
, onde T é do tipo valor é mais rápido queArrayList
. Isso ocorre porqueList<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
temIsSynchronized
propriedade. Portanto, é fácil criar e usar sincronizadoArrayList
. Não encontreiIsSynchronized
propriedades paraList<T>
. Lembre-se também de que esse tipo de sincronização é relativamente ineficiente, msdn ):ArrayList
possuiArrayList.SyncRoot
propriedade que pode ser usada para sincronização ( msdn ).List<T>
não possuiSyncRoot
propriedade, portanto, na construção a seguir, você precisará usar algum objeto se usarList<T>
:fonte
Conforme mencionado na documentação do .NET Framework
Consulte também Coleções não genéricas não devem ser usadas
fonte
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.
fonte
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)
fonte