O .NET oferece um contêiner de lista genérica cujo desempenho é quase idêntico (consulte a pergunta Desempenho de matrizes x listas). No entanto, eles são bastante diferentes na boot.
Os arrays são muito fáceis de inicializar com um valor padrão e, por definição, eles já possuem determinado tamanho:
string[] Ar = new string[10];
Que permite atribuir com segurança itens randoms, digamos:
Ar[5]="hello";
com as coisas da lista são mais complicadas. Eu posso ver duas maneiras de fazer a mesma boot, nenhuma das quais é o que você chamaria de elegante:
List L = new List(10); for (int i=0;i<10;i++) L.Add(null);
ou
string[] Ar = new string[10]; List L = new List(Ar);
O que seria um caminho mais limpo?
EDIT: As respostas até agora referem-se a capacidade, que é outra coisa do que preencher previamente uma lista. Por exemplo, em uma lista recém criada com uma capacidade de 10, não se pode fazer L[2]="somevalue"
EDIT 2: As pessoas perguntam por que eu quero usar listas dessa maneira, como não é o modo como elas devem ser usadas. Eu posso ver duas razões:
Poder-se-ia argumentar bastante convincentemente que as listas são as matrizes da “próxima geração”, adicionando flexibilidade com quase nenhuma 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 class base que oferece funcionalidade padrão como parte de uma estrutura maior. Na funcionalidade padrão que ofereço, o tamanho da lista é conhecido em avançado e, portanto, eu poderia ter usado uma matriz. No entanto, quero oferecer a qualquer class base a chance de estendê-la dinamicamente e, portanto, opto por uma lista.
Eu não posso dizer que preciso disso com muita freqüência – você poderia dar mais detalhes do porquê você quer isso? Eu provavelmente colocaria isso como um método estático em uma class auxiliar:
public static class Lists { public static List RepeatedDefault (int count) { return Repeated(default(T), count); } public static List Repeated (T value, int count) { List ret = new List (count); ret.AddRange(Enumerable.Repeat(value, count)); return ret; } }
Você poderia usar Enumerable.Repeat(default(T), count).ToList()
mas isso seria ineficiente devido ao redimensionamento do buffer.
EDIT: Como observado nos comentários, você poderia fazer Repeated
usar um loop para preencher a lista se você quisesse. Isso seria um pouco mais rápido também. Pessoalmente, eu acho o código usando Repeat
mais descritivo, e suspeito que no mundo real a diferença de desempenho seria irrelevante, mas sua milhagem pode variar.
List L = new List ( new string[10] );
Use o construtor que usa um int (“capacity”) como argumento:
List = new List (10);
EDIT: devo acrescentar que eu concordo com Frederik. Você está usando a Lista de uma maneira que vai contra todo o raciocínio por trás de usá-la em primeiro lugar.
EDIT2:
EDIT 2: O que estou escrevendo atualmente é uma class base oferecendo funcionalidade padrão como parte de uma estrutura maior. Na funcionalidade padrão que ofereço, o tamanho da lista é conhecido em avançado e, portanto, eu poderia ter usado uma matriz. No entanto, quero oferecer a qualquer class base a chance de estendê-la dinamicamente e, portanto, opto por uma lista.
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 que isso é claudicante demonstra que está indo contra o uso pretendido da class.
Por que você está usando uma lista se quiser inicializá-la com um valor fixo? Eu posso entender isso – por causa do desempenho – você quer dar a ele uma capacidade inicial, mas não é uma das vantagens de uma lista sobre um array regular que pode crescer quando necessário?
Quando você faz isso:
List = new List (100);
Você cria uma lista cuja capacidade é 100 inteiros. Isso significa que sua Lista não precisará “crescer” até você adicionar o 101º item. O array subjacente da lista será inicializado com um comprimento de 100.
Inicializando o conteúdo de uma lista como essa não é realmente o que as listas são para. As listas são projetadas para armazenar objects. Se você deseja mapear determinados números para objects específicos, considere o uso de uma estrutura de par de valores-chave como uma tabela de hash ou um dictionary em vez de uma lista.
Se você quiser inicializar a lista com N elementos de algum valor fixo:
public List InitList (int count, T initValue) { return Enumerable.Repeat(initValue, count).ToList(); }
Você parece estar enfatizando a necessidade de uma associação posicional com seus dados, portanto, um arranjo associativo não seria mais adequado?
Dictionary foo = new Dictionary(); foo[2] = "string";
Crie uma matriz com o número de itens que você deseja primeiro e, em seguida, converta a matriz em uma lista.
int[] fakeArray = new int[10]; List list = fakeArray.ToList();
Isso realmente depende do motivo pelo qual você deseja inicializá-lo. Não tenho certeza se inicializá-lo com um certo número de elementos vazios ou nulos é útil. A vantagem das listas é que elas podem crescer conforme necessário.
O construtor de lista usa um parâmetro de capacidade que pode ser usado para preenchê-lo inicialmente.
List = new List (10);
string [] temp = new string[] {"1","2","3"}; List temp2 = temp.ToList();
Você pode usar o Linq para inicializar sua lista com um valor padrão. (Semelhante à resposta de David B. )
var defaultStrings = (new int[10]).Select(x => "my value").ToList();
Vá um passo além e inicialize cada string com valores distintos “string 1”, “string 2”, “string 3”, etc:
int x = 1; var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();
Um aviso sobre IList: MSDN IList Comentários : “IList implementações se enquadram em três categorias: somente leitura, tamanho fixo e tamanho de variável. (…). Para a versão genérica dessa interface, consulte System.Collections.Generic.IList
. ”
IList
não herda de IList
(mas List
implementa IList
e IList
), mas é sempre de tamanho variável . Desde o .NET 4.5, também temos o IReadOnlyList
mas o AFAIK, não existe uma lista genérica de tamanho fixo que seria o que você está procurando.
Esta é uma amostra que usei para o teste da minha unidade. Eu criei uma lista de objects de class. Então usei o forloop para adicionar o número ‘X’ de objects que estou esperando do serviço. Desta forma, você pode adicionar / inicializar uma lista para qualquer tamanho.
public void TestMethod1() { var expected = new List(); for (int i = 0; i < 22; i++)//You add empty initialization here { var temp = new DotaViewer.Interface.DotaHero(); expected.Add(temp); } var nw = new DotaHeroCsvService(); var items = nw.GetHero(); CollectionAssert.AreEqual(expected,items); }
Espero que eu tenha ajudado vocês.
Um pouco tarde, mas a primeira solução que você propôs parece muito mais limpa para mim: você não aloca memory duas vezes. O construtor Even List precisa fazer um loop através do array para copiá-lo; nem sequer sabe de antemão que existem apenas elementos nulos no interior.
1. – aloca o N-loop N Cost: 1 * aloca (N) + N * loop_iteration
2. – alocar N – alocar N + loop () Custo: 2 * alocar (N) + N * loop_iteration
No entanto alocação de lista de loops pode ser mais rápido desde que a lista é uma class interna, mas c # é compilado jit sooo …