Como inicializar uma matriz vazia em c #?

Respostas:

435

Se você vai usar uma coleção que você não conhece antecipadamente o tamanho, há opções melhores do que matrizes.

Use um List<string>- em vez disso, você poderá adicionar quantos itens precisar e, se precisar retornar uma matriz, chame ToArray()a variável.

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

Se você deve criar uma matriz vazia, você pode fazer isso:

string[] emptyStringArray = new string[0]; 
Oded
fonte
1
@Oded - string [] emptyStringArray = nova string [0]; não resulta em uma matriz vazia, não é? Parece que é uma matriz com um elemento em que esse elemento é nulo.
rory.ap
11
@roryap - Não. Isso resulta em um string[]que não possui elementos. Se você tentar acessar emptyStringArray[0], você terá uma #IndexOutOfRangeException
Oded
@ Oded - Obrigado, eu sou bastante novo em c #. No VB, o índice fornecido é o limite superior, não o número de elementos.
rory.ap
1
O que você consideraria melhor: var strings = new string [] {}; ou var strings = nova string [0]; BTW: Eu considero um array vazio um padrão perfeitamente válida para os parâmetros do método: EditItems public void (IEnumerable <Item> toEdit, IEnumerable <longo> toDelete = new long [] {})
realbart
6
@ RickO'Shea - C ++ não é C #. Stroustrup conhece seu C ++ - não tem tanta certeza de que conhece seu C # e o .NET GC. Não vou entrar em guerra religiosa com você.
Oded
181

Tente o seguinte:

string[] a = new string[] { };
hemant
fonte
7
Expandindo esta resposta, você também pode iniciar a matriz com itens sem especificar o tamanho OU tipo, o compilador deduzirá do inicializador: var a = new [] {"a", "b", "c"}; Ainda é uma matriz de cadeias fortemente tipada.
usar o seguinte código
1
Exceção não tratada: System.IndexOutOfRangeException: o índice estava fora dos limites da matriz. em ArrayClass.Main (String [] args). Eu enfrentei esse erro depois que alterei minha variável int [] = new int [] {}
yogesh
6
@ yogesh: Isso é estranho. Quando, por exemplo, escrever int[] variable = new int[]{}e usá-lo, por exemplo, em um loop, como foreach (var s in variable){ Console.WriteLine(s);}o código, é compilado para: int[] args1 = new int[0];e foreach (int num in args1){Console.WriteLine(num);}. Portanto, não deve haver diferença entre usar new int[0]e new int[]{}como os dois são compilados no mesmo código.
Nope
1
@ GlennGordon Absolutamente, mas isso é novo a partir do C # versão 3.0 (de 2007, com o Visual Studio 2008). Essa versão também permite outro formato simples com var, embora apenas para variáveis ​​locais (não para campos). No entanto, no C # 2.0 (Visual Studio 2005) e versões anteriores, era necessário usar a sintaxe desta resposta (ou string[] a = new string[0];).
Jeppe Stig Nielsen,
113

No .NET 4.6, a maneira preferida é usar um novo método Array.Empty:

String[] a = Array.Empty<string>();

A implementação é sucinta, usando como os membros estáticos em classes genéricas se comportam em .Net :

public static T[] Empty<T>()
{
    return EmptyArray<T>.Value;
}

// Useful in number of places that return an empty byte array to avoid
// unnecessary memory allocation.
internal static class EmptyArray<T>
{
    public static readonly T[] Value = new T[0];
}

(código relacionado ao contrato de código removido para maior clareza)

Veja também:

Kobi
fonte
@ Johnson Johnson - Obrigado pela edição, mas eu revirei. Omiti essas linhas de propósito: queria citar apenas a implementação interessante. O contrato e os atributos do código apenas atrapalham a compreensão do que está acontecendo (o link para a fonte tem tudo, é claro). Também adicionei uma nova linha no comentário para evitar a rolagem no Stack Overflow. Se você não se importa, eu prefiro assim. Obrigado!
Kobi
2
Definitivamente, uma melhoria na legibilidade de:Enumerable.Empty<T>().ToArray()
DanielV
Embora esse método seja definitivamente preferido na maioria dos casos, ele não responde à pergunta original. O OP quer criar uma matriz vazia. Array.Empty<T>()se não criar uma matriz. Retorna uma referência a uma matriz pré-alocada.
L26t
33

Você pode inicializá-lo com um tamanho de 0, mas precisará reinicializá-lo quando souber qual é o tamanho, pois não poderá anexá-lo à matriz.

string[] a = new string[0];
MatthiasG
fonte
Esta é a resposta exata
abzarak
7

Não há muito sentido em declarar uma matriz sem tamanho. Uma matriz é sobre o tamanho . Ao declarar uma matriz de tamanho específico, você especifica o número fixo de slots disponíveis em uma coleção que pode conter itens e, portanto, a memória é alocada. Para adicionar algo a ele, você precisará reinicializar de qualquer maneira a matriz existente (mesmo que você esteja redimensionando a matriz, consulte este tópico ). Um dos raros casos em que você desejaria inicializar uma matriz vazia seria passar a matriz como argumento.

Se você deseja definir uma coleção quando não sabe qual o tamanho possível, a matriz não é sua escolha, mas algo como um List<T>ou semelhante.

Dito isto, a única maneira de declarar uma matriz sem especificar o tamanho é ter uma matriz vazia do tamanho 0 . hemant e Alex Dn fornecem duas maneiras. Outra alternativa mais simples é apenas :

string[] a = { };

[ Os elementos dentro do colchete devem ser implicitamente conversíveis no tipo definido, por exemplo,string[] a = { "a", "b" }; ]

Ou ainda outro:

var a = Enumerable.Empty<string>().ToArray();

Aqui está uma maneira mais declarativa :

public static class Array<T>
{
    public static T[] Empty()
    {
        return Empty(0);
    }

    public static T[] Empty(int size)
    {
        return new T[size];
    }
}

Agora você pode ligar para:

var a = Array<string>.Empty();

//or

var a = Array<string>.Empty(5);
nawfal
fonte
1
Não consigo pensar em nenhum uso, exceto quando você passou uma matriz como parâmetro. Existem alguns casos em reflexão em que um método aceita uma matriz de objetos e você pode passar uma matriz vazia para efetuar a ação padrão. Vou editar minha resposta.
Nawfal 29/04
Por exemplo, você tem uma interface implementada por várias classes retornando um IEnumerable e uma das implementações não possui elementos para o método e retorna uma matriz vazia, por exemplo.
Ignacio Soler Garcia
@IgnacioSolerGarcia Gostaria de retornar uma matriz nesse caso, se e somente se for uma aplicação extremamente crítica para o desempenho. Eu vou dizer que as matrizes estão desatualizadas e devem ser evitadas se você puder. Veja isso por Lippert e esta pergunta SO
nawfal 29/04
Lembre-se de que o tipo retornado é IEnumerable, portanto a matriz é somente leitura e não se destina a alterações. Por que eu retornaria uma lista neste caso, por exemplo?
Ignacio Soler Garcia
1
Um caso de uso para uma matriz vazia é simples - quando você deseja preenchê-la com objetos e não sabe quantos irá adicionar!
vapcguy
6

Simples e elegante!

string[] array = {}
disklosr
fonte
Eu mudaria arraypara apenas a, como arrayé uma palavra-chave quando capitalizada. É uma prática ruim usar um nome de palavra-chave como nome de variável - mesmo que o caso seja diferente. E basicamente o mesmo que a minha resposta, exceto que eu tinha String.Emptylá.
vapcguy
1
1. matriz não é uma palavra-chave ac #. Array é uma classe e não uma palavra-chave 2. "a" também é uma prática ruim (talvez pior ainda uma má prática de usar palavras-chave)
disklosr
Sendo técnico. Classe, palavra-chave, define um tipo de objeto e ainda é ruim. Por que você acha que aé ruim?
vapcguy
1
Como nomes de variáveis ​​não descritivos e de uma letra são práticas inadequadas porque não transmitem a razão por trás de defini-las. "array" é certamente um nome melhor que "a". Um nome melhor seria "emptyArray".
disklosr
4

string[] a = new string[0];

ou notação curta:

string[] a = { };

A maneira preferida agora é:

var a = Array.Empty<string>();

Eu escrevi uma expressão regular curta que você pode usar no Visual Studio se quiser substituir alocações de tamanho zero, por exemplo new string[0]. Use a opção Localizar (pesquisa) no Visual Studio com a Expressão regular ativada:

new[ ][a-zA-Z0-9]+\[0\]

Agora Encontre Tudo ou F3 (Localizar Próximo) e substitua tudo por Array.Empty <…> ()!

juFo
fonte
3

Você pode definir o tamanho da matriz em tempo de execução .

Isso permitirá que você faça o que for necessário para calcular dinamicamente o tamanho da matriz. Mas, uma vez definido, o tamanho é imutável.

Array a = Array.CreateInstance(typeof(string), 5);
radarbob
fonte
4
Por que tudo isso? Em tempo de execução, você pode definir o tamanho da matriz de uma variável normalmente:int i = 5; string[] a = new string[i];
Kevin Brock
Bem, acho que com os genéricos isso parece obsoleto.
Radarbob 18/09/2013
2

Eu tentei:

string[] sample = new string[0];

Mas eu só consegui inserir uma string e, em seguida, recebi um erro exceptionOutOfBound, então simplesmente coloquei um tamanho para ela, como

string[] sample = new string[100];

Ou de outra maneira que funcione para mim:

List<string> sample = new List<string>();

Atribuindo valor à lista:

sample.Add(your input);
Cs_Lu
fonte
1

Como eu sei, você não pode fazer array sem tamanho, mas pode usar

List<string> l = new List<string>() 

e depois l.ToArray().

Alex Dn
fonte
1

Combinando as sugestões @nawfal e @Kobi:

namespace Extensions
{
    /// <summary> Useful in number of places that return an empty byte array to avoid unnecessary memory allocation. </summary>
    public static class Array<T>
    {
        public static readonly T[] Empty = new T[0];
    }
}

Exemplo de uso:

Array<string>.Empty

ATUALIZAÇÃO 14-05-2019

(créditos para @Jaider ty)

Melhor uso da API .Net:

public static T[] Empty<T> ();

https://docs.microsoft.com/en-us/dotnet/api/system.array.empty?view=netframework-4.8

Aplica-se a:

.NET Core: 3.0 Pré-visualização 5 2.2 2.1 2.0 1.1 1.0

.NET Framework: 4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6

.NET Standard: 2.1 Visualização 2.0 1.6 1.5 1.4 1.3

...

HTH

ShloEmi
fonte
1
Em .NET Core 2, já existe uma extensão para isso,arr = Array.Empty<string>();
Jaider
iirc, no .NetStandart [4.algo] - também existe.
ShloEmi 14/05/19
0

Você pode fazer:

string[] a = { String.Empty };

Nota: OP significava não ter que especificar um tamanho, não tornar uma matriz sem tamanho

vapcguy
fonte
8
Isso não criará uma matriz de cadeia de comprimento 1?
Sumner Evans
É verdade, mas está limpo. E a OP pediu para declarar a matriz sem precisar indicar um tamanho - isso se encaixa nisso.
Vapcguy
E isso merece um voto negativo, por quê? OP significava não ter que ter specifyum tamanho, não criar uma matriz sizeless.
Vapcguy
1
@vapcguy Eu era o downvoter. Eu me arrependo disso. Eu editei sua resposta para cancelar meu voto negativo. Seu comentário torna a pergunta um pouco duvidosa. Não tenho certeza se é isso que OP significava.
Nawfal
4
O OP pediu uma matriz vazia . Esta matriz não está vazia.
Keith
0

Aqui está um exemplo do mundo real. Nesse sentido, é necessário inicializar a matriz foundFilesprimeiro com comprimento zero.

(Como enfatizado em outras respostas: Isso inicializa não um elemento e, especialmente, um elemento com índice zero, porque isso significaria que a matriz tinha comprimento 1. A matriz tem comprimento zero após esta linha!).

Se a peça = string[0]for omitida, há um erro do compilador!

Isso ocorre por causa do bloco de captura sem religação. O compilador C # reconhece o caminho do código, que a função Directory.GetFiles()pode lançar uma exceção, para que a matriz possa ser não inicializada.

Antes que alguém diga, não reler a exceção seria um tratamento incorreto de erros: isso não é verdade. O tratamento de erros deve atender aos requisitos.

Nesse caso, supõe-se que o programa continue no caso de um diretório que não possa ser lido e não quebre - o melhor exemplo é uma função que atravessa uma estrutura de diretórios. Aqui, a manipulação de erros está apenas registrando-a. É claro que isso poderia ser feito melhor, por exemplo, coletando todos os diretórios com GetFiles(Dir)chamadas com falha em uma lista, mas isso levará muito longe aqui.

É suficiente afirmar que evitar throwé um cenário válido e, portanto, a matriz deve ser inicializada com o comprimento zero. Seria o suficiente para fazer isso no bloco catch, mas seria um estilo ruim.

A chamada para GetFiles(Dir)redimensionar a matriz.

string[] foundFiles= new string[0];
string dir = @"c:\";
try
{
    foundFiles = Directory.GetFiles(dir);  // Remark; Array is resized from length zero
}
// Please add appropriate Exception handling yourself
catch (IOException)
{
  Console.WriteLine("Log: Warning! IOException while reading directory: " + dir);
  // throw; // This would throw Exception to caller and avoid compiler error
}

foreach (string filename in foundFiles)
    Console.WriteLine("Filename: " + filename);
Philm
fonte