.NET oferece um contêiner de lista genérico cujo desempenho é quase idêntico (consulte a pergunta Desempenho de matrizes vs. listas). No entanto, eles são bastante diferentes na inicialização.
Os arrays são muito fáceis de inicializar com um valor padrão e, por definição, eles já têm um determinado tamanho:
string[] Ar = new string[10];
O que permite atribuir itens aleatórios com segurança, por exemplo:
Ar[5]="hello";
com lista as coisas são mais complicadas. Posso ver duas maneiras de fazer a mesma inicialização, nenhuma delas é o que você chamaria de elegante:
List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);
ou
string[] Ar = new string[10];
List<string> L = new List<string>(Ar);
Qual seria uma maneira mais limpa?
EDITAR: As respostas até agora referem-se à capacidade, que é algo mais do que preencher previamente uma lista. Por exemplo, em uma lista recém-criada com capacidade para 10, não se pode fazerL[2]="somevalue"
EDIT 2: As pessoas se perguntam por que eu quero usar listas dessa forma, já que não é a maneira que elas devem ser usadas. Posso ver duas razões:
Alguém poderia argumentar de forma bastante convincente que as listas são os arrays da "próxima geração", adicionando flexibilidade quase sem penalidade. Portanto, deve-se usá-los por padrão. Estou apontando que eles podem não ser tão fáceis de inicializar.
O que estou escrevendo atualmente é uma classe base que oferece funcionalidade padrão como parte de uma estrutura maior. Na funcionalidade padrão que ofereço, o tamanho da Lista é conhecido com antecedência e, portanto, eu poderia ter usado um array. No entanto, quero oferecer a qualquer classe base a chance de estendê-la dinamicamente e, portanto, opto por uma lista.
List
não é um substituto paraArray
. Eles resolvem problemas distintos. Se você deseja um tamanho fixo, deseja umArray
. Se você usar umList
, você está fazendo isso errado.Respostas:
Não posso dizer que preciso disso com muita frequência - você poderia dar mais detalhes sobre por que deseja isso? Eu provavelmente o colocaria como um método estático em uma classe auxiliar:
Você poderia usar,
Enumerable.Repeat(default(T), count).ToList()
mas isso seria ineficiente devido ao redimensionamento do buffer.Observe que se
T
for um tipo de referência, ele armazenarácount
cópias da referência passada para ovalue
parâmetro - portanto, todas farão referência ao mesmo objeto. Isso pode ou não ser o que você deseja, dependendo do seu caso de uso.EDIT: Conforme observado nos comentários, você pode
Repeated
usar um loop para preencher a lista, se quiser. Isso seria um pouco mais rápido também. Pessoalmente, acho o códigoRepeat
mais descritivo e suspeito que no mundo real a diferença de desempenho seria irrelevante, mas sua milhagem pode variar.fonte
Enumerable.Repeat(...).ToArray()
, que não é como estou usando.Enumerable.Repeat()
da seguinte maneira (implementadoPair
como o equivalente em C ++):Enumerable.Repeat( new Pair<int,int>(int.MaxValue,-1), costs.Count)
percebendo o efeito colateral, que oList
estava cheio de cópias referenciadas para um único objeto. Mudar um elementomyList[i].First = 1
mudou cada elemento no todoList
. Levei horas para encontrar esse bug. Vocês conhecem alguma solução para esse problema (exceto apenas para usar um loop comum e usar.Add(new Pair...)
?fonte
L
simplesmente reutilizará a memória do estado emstring[10]
que se encontra (o armazenamento de backup de uma lista também é um array) ou alocará uma nova memória própria e, em seguida, copiará o conteúdo destring[10]
?string[10]
obterá lixo coletado automaticamente seL
selecionar a rota posterior.Use o construtor que leva um int ("capacidade") como argumento:
EDIT: Devo acrescentar que concordo com Frederik. Você está usando a Lista de uma forma que vai contra todo o raciocínio por trás de seu uso.
EDIT2:
Por que alguém precisaria saber o tamanho de uma lista com todos os valores nulos? Se não houver valores reais na lista, eu esperaria que o comprimento fosse 0. De qualquer forma, o fato de ser desordenado demonstra que vai contra o uso pretendido da classe.
fonte
new List<string>()
que diz respeito ao problema . Parabéns por conseguir tantos votos positivos :)list[index] = obj;
e usar alguns outros recursos de lista.Crie uma matriz com o número de itens que você deseja primeiro e, em seguida, converta a matriz em uma Lista.
fonte
Por que você está usando uma lista se deseja inicializá-la com um valor fixo? Posso entender que, por uma questão de desempenho, você queira dar a ele uma capacidade inicial, mas uma das vantagens de uma lista em relação a um array regular não é que ela pode crescer quando necessário?
Quando você faz isso:
Você cria uma lista cuja capacidade é 100 inteiros. Isso significa que sua lista não precisará 'crescer' até que você adicione o 101º item. A matriz subjacente da lista será inicializada com um comprimento de 100.
fonte
Inicializar o conteúdo de uma lista como essa não é realmente para o que as listas existem. As listas são projetadas para conter objetos. Se você deseja mapear números específicos para objetos específicos, considere o uso de uma estrutura de par de valores-chave, como uma tabela hash ou dicionário, em vez de uma lista.
fonte
Você parece estar enfatizando a necessidade de uma associação posicional com seus dados, então uma matriz associativa não seria mais adequada?
fonte
Se você deseja inicializar a lista com N elementos de algum valor fixo:
fonte
Você pode usar o Linq para inicializar inteligentemente sua lista com um valor padrão. (Semelhante à resposta de David B. )
Vá um passo adiante e inicialize cada string com valores distintos "string 1", "string 2", "string 3", etc:
fonte
fonte
A resposta aceita (aquela com a marca de seleção verde) tem um problema.
O problema:
Recomendo alterar a linha acima para realizar uma cópia do objeto. Existem muitos artigos diferentes sobre isso:
Se você deseja inicializar cada item da lista com o construtor padrão, em vez de NULL, adicione o seguinte método:
fonte
Um aviso sobre IList: MSDN IList Observações : "As implementações IList se enquadram em três categorias: somente leitura, tamanho fixo e tamanho variável. (...). Para a versão genérica desta interface, consulte
System.Collections.Generic.IList<T>
."IList<T>
NÃO herda deIList
(masList<T>
implementa ambosIList<T>
eIList
), mas é sempre de tamanho variável . Desde o .NET 4.5, nós também temos oIReadOnlyList<T>
AFAIK, não há uma lista genérica de tamanho fixo que seria o que você está procurando.fonte
Este é um exemplo que usei para meu teste de unidade. Criei uma lista de objetos de classe. Então usei o forloop para adicionar o número 'X' de objetos que estou esperando do serviço. Desta forma, você pode adicionar / inicializar uma lista para qualquer tamanho determinado.
Espero ter ajudado vocês.
fonte
Um pouco tarde, mas a primeira solução que você propôs parece muito mais limpa para mim: você não aloca memória duas vezes. Mesmo o construtor List precisa fazer um loop através do array para copiá-lo; nem mesmo sabe de antemão que há apenas elementos nulos dentro.
1. - alocar N - loop N Custo: 1 * alocar (N) + N * loop_iteration
2. - alocar N - alocar N + loop () Custo: 2 * alocar (N) + N * loop_iteration
No entanto, a alocação e os loops de List podem ser mais rápidos, já que List é uma classe integrada, mas C # é compilado por jit então ...
fonte