Parece que o List<T>
C # pode fazer tudo o que uma matriz pode fazer e muito mais, além de parecer tão eficiente em memória e desempenho quanto uma matriz.
Então, por que eu iria querer usar uma matriz?
Obviamente, não estou perguntando sobre casos em que uma API ou outra restrição externa (ou seja, a função Main) exige que eu use uma matriz ... Estou apenas perguntando sobre a criação de novas estruturas de dados no meu próprio código.
c#
data-types
JoelFan
fonte
fonte
List<T>
is also just as efficient in memory and performance as an array
- hum. De onde você tirou essa noção?var test = new string[5,5]
;)Respostas:
A mesma razão que eu não dirijo um caminhão quando vou trabalhar. Eu não uso algo que não usarei os recursos.
Antes de tudo, uma matriz é uma construção primitiva; portanto, uma matriz é mais rápida e eficiente que uma Lista <>, com certeza, portanto seu argumento não é verdadeiro. A matriz também está disponível em todos os lugares e é conhecida pelos desenvolvedores que usam diferentes idiomas e plataformas.
O motivo mais importante de eu usar uma matriz em vez de uma Lista <> é sugerir que os dados são de comprimento fixo . Se não adicionar ou remover nenhum item dessa coleta de dados, quero garantir que o tipo reflita isso.
Outra coisa é dizer que você está implementando uma nova estrutura de dados e que leu alguns documentos sobre ela. Agora, ao implementar algoritmos específicos, você nem sempre pode confiar na implementação de outro tipo de um objetivo geral. Ele muda do .NET para o Mono e até entre diferentes versões da estrutura.
E às vezes é mais fácil portar um pedaço de código que usa uma matriz em vez de um tipo dependente da estrutura.
fonte
List<T>
é implementada usando uma matriz? Se você conhece a contagem de elementos de antemão (o que você precisa saber ao usar uma matriz), pode usar esse conhecimento ao inicializar a lista.Você precisa de matrizes para gerenciar sua coleção de estruturas mutáveis , é claro, e o que faríamos sem elas.
(observe que pode haver alguns casos em que uma matriz de estrutura mutável é desejável, mas geralmente esse comportamento diferente de estruturas mutáveis dentro de matrizes versus outras coleções é uma fonte de erros que devem ser evitados)
Mais a sério, você precisa de uma matriz se quiser passar um elemento por referência . ie
Isso pode ser útil para código seguro de thread sem bloqueio.
Você precisará de uma matriz se desejar, rápida e eficientemente, inicializar sua coleção de tamanho fixo com o valor padrão .
(observe que seria possível implementar um construtor para a lista que faz o mesmo, mas o c # não oferece esse recurso)
você precisa de uma matriz se quiser copiar com eficiência partes da coleção
(novamente, isso também pode ser implementado para a lista, mas esse recurso não existe no c #)
fonte
Raramente , você terá um cenário em que sabe que precisa de um número fixo de elementos. Da perspectiva do design, isso deve ser evitado. Se você precisar de três coisas, a natureza dos negócios significa que muitas vezes precisará de quatro no próximo lançamento.
Ainda assim, quando esse cenário raro realmente ocorre, é útil usar uma matriz para impor essa invariante de tamanho fixo. Ele fornece um sinal para outros programadores de que é um tamanho fixo e ajuda a evitar o uso indevido onde alguém adiciona ou remove um elemento - quebrando as expectativas em outras partes do código.
fonte
Sua pergunta já foi respondida antes .
Não é. Da pergunta que eu vinculei:
As matrizes são duas vezes mais rápidas em certos casos importantes. Estou certo de que o uso da memória também difere de maneira não trivial.
Como a principal premissa de sua pergunta foi derrotada, presumo que isso responda à sua pergunta. Além disso, algumas vezes as matrizes são impostas a você pela API do Win32, ou pelo sombreador da sua GPU ou por outra biblioteca que não seja da DotNet.
Mesmo no DotNet, alguns métodos consomem e / ou retornam matrizes (como
String.Split
). O que significa que agora você deve comer o custo de ligarToList
eToArray
o tempo todo, ou deve conformar e usar a matriz, possivelmente continuando o ciclo propagando isso para usuários ruins do seu código.Mais perguntas e respostas sobre o estouro de pilha sobre este tópico:
List<T>
: quando usar qual?List<>
?fonte
Além dos motivos listados em outras respostas, o array literal leva menos caracteres para declarar:
O uso da matriz em vez de
List
torna o código um pouco mais curto e um pouco mais legível nos casos em que (1) você precisa passar qualquerIEnumerable<T>
literal ou (2) onde outras funcionalidades deList
não importam e você precisa usar algum tipo de lista literal.Fiz isso ocasionalmente em testes de unidade.
fonte
foreach( var x in new []{ a, b, c ) ) DoStuff( x )
ounew []{ a, b, c ).Select( ... )
etc #Isso é estritamente da perspectiva do OO.
Embora eu não consiga pensar em um motivo para transmitir apenas uma matriz, certamente vejo situações em que uma representação de matriz interna à classe é provavelmente a melhor escolha.
Embora existam outras opções que oferecem características semelhantes, nenhuma parece tão intuitiva quanto uma matriz para problemas ao lidar com permutações de processamento, aninhadas para loops, representação de matrizes, bitmaps e algoritmos de intercalação de dados.
Há um número substancial de campos científicos que dependem extensivamente da matemática matricial. (por exemplo, processamento de imagem, correção de erro de dados, processamento de sinal digital, uma resma de problemas matemáticos aplicados). A maioria dos algoritmos nesses campos é escrita em termos do uso de matrizes / matrizes multidimensionais. Portanto, seria mais natural implementar os algoritmos conforme eles são definidos, em vez de torná-los mais amigáveis ao "software" à custa de perder os vínculos diretos com os papéis nos quais os algoritmos se baseiam.
Como eu disse, nesses casos, você provavelmente pode usar listas, mas isso adiciona mais uma camada de complexidade sobre o que já são algoritmos complexos.
fonte
Na verdade, isso vale para outras linguagens que também possuem listas (como Java ou Visual Basic). Há casos em que você precisa usar uma matriz porque um método retorna uma matriz em vez de uma Lista.
Em um programa real, não acho que uma matriz seja usada com muita frequência, mas às vezes você sabe que os dados terão um tamanho fixo e você gosta do pequeno ganho de desempenho obtido ao usar uma matriz. A micro-otimização seria um motivo válido, assim como um método para retornar uma lista ou a necessidade de uma estrutura de dados multidimensional.
fonte
list<T>
wherevector<T>
will work é uma péssima idéia em C / C ++.vector<T> x
compila muito bem para mim no C . :-)list<T>
. Basicamente, eu já vi muitos problemas de desempenho causados por desenvolvedores apenas usando listas por padrão quando uma matriz era uma escolha melhor.Bem, encontrei um uso para matrizes em um jogo que escrevi. Usei-o para criar um sistema de inventário com um número fixo de slots. Isso teve vários benefícios:
Imaginei que, se alguma vez precisasse "aumentar" o tamanho do inventário, poderia fazê-lo transferindo os itens antigos para a nova matriz, mas como o inventário foi corrigido pelo espaço na tela e não era necessário aumentá-lo dinamicamente / menor, funcionou bem para o propósito para o qual eu estava usando.
fonte
Se você estiver percorrendo todos os elementos de uma lista, não, uma matriz não é necessária; a seleção 'próxima' ou 'arbitrária sem substituição' será adequada.
Mas se o seu algoritmo precisar de acesso aleatório aos elementos da coleção, sim, uma matriz será necessária.
Isso é um pouco análogo a "é necessário ir?". Em uma linguagem moderna razoável, isso não é necessário. Mas se você separar as abstrações, em algum momento, isso é tudo o que está realmente disponível para você, ou seja, a única maneira de implementar essas abstrações é com o recurso 'desnecessário'. (É claro que a analogia não é perfeita, acho que ninguém diz que matrizes são uma prática ruim de programação; são fáceis de entender e pensar).
fonte
List<T>
.Compatibilidade herdada.
Todos formam experiência pessoal:
Programadores legados - meu colega usa matrizes em todos os lugares, já faz mais de 30 anos, boa sorte mudando de idéia com suas novas idéias fangled.
Código legado - foo (barra de matriz []), certifique-se de que você pode usar uma função de matriz de lista / vetor / coleção, mas se você não estiver usando nenhum desses recursos adicionais, é mais fácil usar uma matriz para começar, geralmente mais legível sem a alternância de tipos.
Chefe legado - meu chefe era um bom programador antes de ingressar na administração há muitos anos e ainda acha que está atualizado: "estava usando matrizes" pode encerrar uma reunião, explicando o que é uma coleção e pode custar o almoço de todos.
fonte
1) Não existe uma versão multidimensional da lista. Se seus dados tiverem mais de uma dimensão, será muito ineficiente usar listas.
2) Quando você lida com um grande número de pequenos tipos de dados (por exemplo, um mapa em que tudo o que você tem é um byte para o tipo de terreno), pode haver diferenças consideráveis de desempenho devido ao armazenamento em cache. A versão do array carrega vários itens por leitura de memória, a versão da lista carrega apenas um. Além disso, a versão do array contém várias vezes mais células no cache que a versão da lista - se você estiver processando repetidamente os dados, isso pode fazer uma grande diferença se a versão do array se encaixar no cache, mas a versão da lista não.
Para um caso extremo, considere o Minecraft. (Sim, não está escrito em C #. O mesmo motivo se aplica.)
fonte
T[,]
) são mais lentas que as matrizes irregulares equivalentes (por exemploT[][]
) .Uma matriz de 100 elementos de algum tipo T encapsula 100 variáveis independentes do tipo T. Se T for um tipo de valor que possui um campo público mutável do tipo Q e um do tipo R, cada elemento da matriz encapsulará variáveis independentes dos tipos Q e R. A matriz como um todo encapsulará 100 variáveis independentes do tipo Q e 100 variáveis independentes do tipo R; qualquer uma dessas variáveis pode ser acessada individualmente sem afetar nenhuma outra. Nenhum tipo de coleção além de matrizes pode permitir que os campos de estruturas sejam usados como variáveis independentes.
Se T passou a ser um tipo de classe com campos mutáveis públicos do tipo Q e R, cada elemento da matriz mantém a única referência, em qualquer lugar do universo, a uma instância de
T
, e se nenhum dos elementos da matriz jamais ser modificado para identificar um objeto para o qual existe qualquer referência externa, o array efetivamente encapsulará 100 variáveis independentes do tipo Q e 100 variáveis independentes do tipo R. Outros tipos de coleções podem imitar o comportamento de uma matriz, mas se o único objetivo da matriz é encapsular 100 variáveis do tipo Q e 100 do tipo R, encapsular cada par de variáveis em seu próprio objeto de classe é uma maneira cara de fazer isso. Mais distante,o uso de uma matriz ou coleção do tipo de classe mutável cria a possibilidade de que as variáveis identificadas pelos elementos da matriz não sejam independentes .Se um tipo deve se comportar como algum tipo de objeto, deve ser um tipo de classe ou uma estrutura de campo privado que não oferece outro meio de mutação além da substituição. Se, no entanto, um tipo deve se comportar como um monte de variáveis relacionadas, mas independentes, coladas com fita adesiva, deve-se usar um tipo que é um monte de variáveis coladas com fita adesiva - uma estrutura de campo exposto . Matrizes desse tipo são muito eficientes para trabalhar e possuem semânticas muito limpas. O uso de qualquer outro tipo levará a semântica confusa, desempenho inferior ou ambos.
fonte
Uma diferença importante é a alocação de memória. Por exemplo, atravessar uma lista vinculada pode resultar em muitas falhas de cache e desempenho mais lento, enquanto uma matriz representa um pedaço contíguo de memória contendo várias instâncias de algum tipo de dados específico, e atravessá-la para ter mais chances de atingir a CPU cache.
Obviamente, uma matriz de referências a objetos pode não se beneficiar tanto dos acertos no cache, pois a desreferenciação ainda pode levá-lo a qualquer lugar na memória.
Depois, há implementações de lista, como ArrayList, que implementam uma lista usando uma matriz. Eles são primitivos úteis para ter.
fonte
List<T>
, que não é implementado usando uma lista vinculada, mas usando uma matriz (é essencialmente equivalente aArrayList<T>
em Java).Aqui estão algumas orientações que você pode usar para selecionar
Array
e quando selecionarList
.Array
ao retornar de um método.List
como a variável ao construir o valor de retorno (dentro do método). Em seguida, use.ToArray()
ao retornar do método.Em geral, use um
Array
quando você não pretende que o consumidor adicione itens à coleção. UseList
quando você pretende que o consumidor adicione itens à coleção.Array
destina-se a lidar com coleções "estáticas", enquantoList
destina-se a lidar com coleções "dinâmicas".fonte
Array
vez deList
. É bom ouvir seus pensamentos!