ArrayList vs List <> em c #


412

Qual é a diferença entre ArrayListeList<> em c #?

É apenas que List<>tem um tipo enquanto ArrayListnão?


5
possível duplicação de ArrayList vs List <object>
John Saunders

5
É 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
goodeye

Encontrou este blog muito útil, pode ajudar. Pensei que deveria compartilhar o link: fintechexplained.blogspot.co.uk/2017/07/…
InfoLearner

Respostas:


533

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


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.

Fonte: lista ArrayList vs. genérica para tipos primitivos e 64 bits


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

Mais informações aqui Sincronização de threads no .Net Framework


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)
  • Boxe e Unboxing não acontecerão.
  • Digite seguro.
  • É mais novo.

Exemplo:

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/

insira a descrição da imagem aqui

Nota : Você deve conhecer os Genéricos antes de entender a diferença: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/


4

ArrayListé a coleta de tipos diferentes de dados, enquanto List<>a coleta de tipos semelhantes de suas próprias dependências.


3

ArrayListnão são do tipo seguro, enquanto List<T>são do tipo seguro. Simples :).


2

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>: insira a descrição da imagem aqui

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: insira a descrição da imagem aqui

Escrevi uma análise detalhada do que se passa com o ArrayListcená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 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.


1

Eu acho que as diferenças entre ArrayListe List<T>são:

  1. 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).
  2. Muitas fontes dizem - geralmente ArrayListusadas apenas para compatibilidade com versões anteriores. (não é uma diferença real, mas acho que é uma nota importante).
  3. A reflexão é mais fácil com nongeneric ArrayListseguidaList<T>
  4. 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 = 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
  5. 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 = new ArrayList();
    lock(myCollection.SyncRoot) //  ofcourse you can use another object for this goal
    {
        foreach (object item in myCollection)
        {
            // ...
        }
    }

0

Conforme mencionado na documentação do .NET Framework

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

Consulte também Coleções não genéricas não devem ser usadas

A tabela mostra como os tipos de coleção não genéricos podem ser substituídos por seus equivalentes genéricos


-2

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

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.

Tom Johnson (uma entrada ... uma saída)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.