¿Cómo inicializo una matriz vacía en C #?

Respuestas:

436

Si va a utilizar una colección que no conoce el tamaño de antemano, hay mejores opciones que las matrices.

Utilice en su List<string>lugar: le permitirá agregar tantos elementos como necesite y, si necesita devolver una matriz, llame ToArray()a la variable.

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

Si debe crear una matriz vacía, puede hacer esto:

string[] emptyStringArray = new string[0]; 
Oded
fuente
1
@Oded - cadena [] emptyStringArray = nueva cadena [0]; no da como resultado una matriz vacía, ¿verdad? Parece que es una matriz con un elemento donde ese elemento es nulo.
rory.ap
11
@roryap - No. Da como resultado un string[]que no tiene elementos. Si intentas acceder emptyStringArray[0], recibirás unIndexOutOfRangeException
Fecha de
@Oded - Gracias, soy bastante nuevo en C #. En VB, el índice proporcionado es el límite superior, no el número de elementos.
rory.ap
1
Qué consideraría mejor: var strings = new string [] {}; o var cadenas = nueva cadena [0]; Por cierto: considero que una matriz vacía es un valor predeterminado perfectamente válido para los parámetros del método: public Void EditItems (IEnumerable <Item> toEdit, IEnumerable <long> toDelete = new long [] {})
realbart
66
@ RickO'Shea - C ++ no es C #. Stroustrup conoce su C ++, no tan seguro de saber su C # y el GC .NET. No voy a entrar en una guerra religiosa contigo.
Oded
182

Prueba esto:

string[] a = new string[] { };
hemant
fuente
77
Ampliando esta respuesta, también puede iniciar la matriz con elementos sin especificar el tamaño O tipo, el compilador deducirá del inicializador: var a = new [] {"a", "b", "c"}; Esta sigue siendo una matriz de cadenas fuertemente tipada.
Nick VanderPyle
1
Excepción no controlada: System.IndexOutOfRangeException: el índice estaba fuera de los límites de la matriz. en ArrayClass.Main (String [] args). Enfrenté este error después de cambiar mi int [] variable = new int [] {}
yogesh
66
@yogesh: Eso es extraño. Cuando, por ejemplo, lo escribe int[] variable = new int[]{}y lo usa, por ejemplo, en un bucle como foreach (var s in variable){ Console.WriteLine(s);}el código se compila en: int[] args1 = new int[0];y foreach (int num in args1){Console.WriteLine(num);}. Por lo tanto, no debería haber diferencia entre usar new int[0]y new int[]{}ya que ambos se compilan en el mismo código.
No
1
@GlennGordon Absolutamente, pero eso es nuevo a partir de la versión 3.0 de C # (desde 2007, con Visual Studio 2008). Esa versión también permite otro formato simple var, aunque solo para variables locales (no para campos). Sin embargo, en C # 2.0 (Visual Studio 2005) y versiones anteriores, tenía que usar la sintaxis de esta respuesta (o string[] a = new string[0];).
Jeppe Stig Nielsen
114

En .NET 4.6, la forma preferida es utilizar un nuevo método Array.Empty:

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

La implementación es sucinta, utilizando cómo se comportan los miembros estáticos en clases genéricas en .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 con el código del contrato eliminado para mayor claridad)

Ver también:

Kobi
fuente
@Cole Johnson: gracias por la edición, pero la retiré. Omití estas líneas a propósito: quería citar solo la implementación interesante. El contrato de código y los atributos solo interfieren en la comprensión de lo que está sucediendo (el enlace a la fuente lo tiene todo, por supuesto). También agregué una nueva línea en el comentario para evitar desplazarse por Stack Overflow. Si no te importa, lo prefiero de esta manera. ¡Gracias!
Kobi
2
Definitivamente una mejora para la legibilidad de:Enumerable.Empty<T>().ToArray()
DanielV
Aunque este método es definitivamente preferido en la mayoría de los casos, no responde la pregunta original. El OP quiere crear una matriz vacía. Array.Empty<T>()no no crear una matriz. Devuelve una referencia a una matriz preasignada.
l33t
33

Puede iniciarlo con un tamaño de 0, pero tendrá que reiniciarlo, cuando sepa cuál es el tamaño, ya que no puede agregarlo a la matriz.

string[] a = new string[0];
MatthiasG
fuente
Esta es la respuesta precisa
abzarak
7

No tiene mucho sentido declarar una matriz sin tamaño. Una matriz tiene aproximadamente el tamaño . Cuando declara una matriz de tamaño específico, especifica el número fijo de ranuras disponibles en una colección que puede contener cosas y, en consecuencia, se asigna memoria. Para agregarle algo, deberá reiniciar la matriz existente de todos modos (incluso si está cambiando el tamaño de la matriz, vea este hilo ). Uno de los casos raros en los que desearía inicializar una matriz vacía sería pasar la matriz como argumento.

Si desea definir una colección cuando no sabe de qué tamaño podría ser, la matriz no es su elección, sino algo así como un List<T> ao similar.

Dicho esto, la única forma de declarar una matriz sin especificar el tamaño es tener una matriz vacía de tamaño 0 . Hemant y Alex Dn ofrece dos formas. Otra alternativa más simple es simplemente :

string[] a = { };

[ Los elementos dentro del paréntesis deben ser implícitamente convertibles al tipo definido, por ejemplo,string[] a = { "a", "b" }; ]

O aún otro:

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

Aquí hay una forma más declarativa :

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

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

Ahora puedes llamar:

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

//or

var a = Array<string>.Empty(5);
nawfal
fuente
1
No puedo pensar en ningún uso, excepto cuando tienes que pasar una matriz como parámetro. Hay algunos casos en reflexión en los que un método acepta una matriz de objetos y es posible que desee pasar una matriz vacía para realizar una acción predeterminada. Editaré mi respuesta.
nawfal
Por ejemplo, tiene una interfaz implementada por varias clases que devuelven un IEnumerable y una de las implementaciones no tiene elementos para el método y devuelve una matriz vacía, por ejemplo.
Ignacio Soler García
@IgnacioSolerGarcia Devolvería una matriz en ese caso si y solo si es una aplicación extremadamente crítica para el rendimiento. Diré que las matrices están desactualizadas y deben evitarse si puede. Vea esto por Lippert y esta pregunta SO
nawfal
Tenga en cuenta que el tipo devuelto es IEnumerable, por lo que la matriz es de solo lectura y no está destinada a cambiar. ¿Por qué devolvería una Lista en este caso, por ejemplo?
Ignacio Soler Garcia
1
Un caso de uso para una matriz vacía es simple: cuando desea llenarlo con objetos y no sabe cuántos agregará.
vapcguy
6

Simple y elegante!

string[] array = {}
disklosr
fuente
Cambiaría arraya justo a, ya que arrayes una palabra clave cuando se escribe con mayúscula. Es una mala práctica usar un nombre de palabra clave como nombre de variable, incluso si el caso es diferente. Y básicamente lo mismo que mi respuesta, excepto que tenía String.Emptyallí.
vapcguy
1
1. array no es una palabra clave ac #. La matriz es una clase y no una palabra clave 2. "a" también es una mala práctica (quizás una peor práctica que usar palabras clave)
disklosr
Siendo técnico. Clase, palabra clave, define un tipo de objeto y sigue siendo malo. ¿Por qué crees que aes malo?
vapcguy
1
Debido a que los nombres de variables no descriptivos y de una letra son una mala práctica porque no transmiten la razón detrás de definirlos. "array" es ciertamente un nombre mejor que "a". Un nombre mejor sería "matriz vacía".
disklosr
4

string[] a = new string[0];

o notación corta:

string[] a = { };

La forma preferida ahora es:

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

He escrito una breve expresión regular que puede usar en Visual Studio si desea reemplazar las asignaciones de longitud cero, por ejemplo new string[0]. Use Buscar (buscar) en Visual Studio con la opción Expresión regular activada:

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

Ahora Buscar todo o F3 (Buscar siguiente) y reemplazar todo con Array.Empty <...> ()!

juFo
fuente
3

Puede definir el tamaño de la matriz en tiempo de ejecución .

Esto le permitirá hacer lo que sea para calcular dinámicamente el tamaño de la matriz. Pero, una vez definido, el tamaño es inmutable.

Array a = Array.CreateInstance(typeof(string), 5);
radarbob
fuente
44
¿Por qué hacer todo eso? En tiempo de ejecución, puede definir el tamaño de matriz a partir de una variable normalmente:int i = 5; string[] a = new string[i];
Kevin Brock
Bueno, supongo que con los genéricos esto parece ser obsoleto.
radarbob
2

Había intentado:

string[] sample = new string[0];

Pero solo pude insertar una cadena en él, y luego recibí un error de excepciónOutOfBound, así que simplemente le puse un tamaño, como

string[] sample = new string[100];

O de otra manera que funcione para mí:

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

Asignación de valor para la lista:

sample.Add(your input);
Cs_Lu
fuente
1

Como sé, no puedes hacer una matriz sin tamaño, pero puedes usar

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

y luego l.ToArray().

Alex Dn
fuente
1

Combinando sugerencias de @nawfal y @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];
    }
}

Ejemplo de uso:

Array<string>.Empty

ACTUALIZACIÓN 2019-05-14

(créditos a @Jaider ty)

Mejor uso de .Net API:

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

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

Se aplica a:

.NET Core: 3.0 Vista previa 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 Vista previa 2.0 1.6 1.5 1.4 1.3

...

HTH

ShloEmi
fuente
1
En .NET Core 2, ya hay una extensión para elloarr = Array.Empty<string>();
Jaider,
iirc, en .NetStandart [4.algo] - también lo hay.
ShloEmi
0

Tu puedes hacer:

string[] a = { String.Empty };

Nota: OP significa no tener que especificar un tamaño, no hacer una matriz sin apresto

vapcguy
fuente
8
¿No creará esto un conjunto de cadenas de longitud 1?
Sumner Evans
Es cierto, pero está despejado. Y OP solicitó declarar la matriz sin tener que indicar un tamaño, esto se ajusta a eso.
vapcguy
Y eso merece un voto negativo, ¿por qué? OP significaba no tener specifyun tamaño, no hacer una matriz sizeless.
vapcguy
1
@vapcguy Yo era el votante negativo. Me arrepiento de ello. He editado su respuesta para cancelar mi voto negativo. Su comentario hace que la pregunta sea un poco dudosa. No estoy seguro si eso es lo que OP quiso decir.
nawfal
44
El OP solicitó una matriz vacía . Esta matriz no está vacía.
Keith,
0

Aquí hay un ejemplo del mundo real. En esto es necesario inicializar la matriz foundFilesprimero a longitud cero.

(Como se enfatizó en otras respuestas: Esto inicializa no un elemento y especialmente un elemento con índice cero porque eso significaría que la matriz tenía longitud 1. ¡La matriz tiene longitud cero después de esta línea!).

Si = string[0]se omite la parte , ¡hay un error de compilación!

Esto se debe al bloque de captura sin volver a lanzar. El compilador de C # reconoce la ruta del código, que la función Directory.GetFiles()puede lanzar una excepción, de modo que la matriz podría no ser inicializada.

Antes de que nadie diga, no volver a lanzar la excepción sería un mal manejo de errores: esto no es cierto. El manejo de errores debe cumplir con los requisitos.

En este caso, se supone que el programa debe continuar en el caso de un directorio que no se puede leer, y no se rompe, el mejor ejemplo es una función que atraviesa una estructura de directorio. Aquí el manejo de errores es solo registrarlo. Por supuesto, esto podría hacerse mejor, por ejemplo, recopilar todos los directorios con erroresGetFiles(Dir) llamadas en una lista, pero esto conducirá demasiado lejos aquí.

Es suficiente afirmar que evitar throwes un escenario válido, por lo que la matriz debe inicializarse a la longitud cero. Sería suficiente hacer esto en el bloque catch, pero sería un mal estilo.

La llamada a GetFiles(Dir)cambiar el tamaño de la 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
fuente