Come posso inizializzare un array vuoto in C #?


328

È possibile creare un array vuoto senza specificare la dimensione?

Ad esempio, ho creato:

String[] a = new String[5];

Possiamo creare l'array di stringhe sopra senza le dimensioni?


2
stackoverflow.com/questions/151936/… u controlla questo link, può aiutarti a capire chiaramente le cose della matrice
Ravi Gadag

Risposte:


436

Se si intende utilizzare una raccolta di cui non si conosce in anticipo la dimensione, esistono opzioni migliori rispetto alle matrici.

Usa List<string>invece un - ti permetterà di aggiungere tutti gli elementi di cui hai bisogno e se devi restituire un array, chiama ToArray()la variabile.

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

Se è necessario creare un array vuoto, è possibile farlo:

string[] emptyStringArray = new string[0]; 

1
@Oded - string [] emptyStringArray = new string [0]; non risulta in un array vuoto, vero? Sembra che sia un array con un elemento in cui quell'elemento è nullo.
rory.ap,

11
@roryap - No. Si traduce in un string[]che non ha elementi. Se provi ad accedere emptyStringArray[0], riceverai unIndexOutOfRangeException
Oded il

@Oded - Grazie, sono abbastanza nuovo in C #. In VB, l'indice fornito è il limite superiore, non il numero di elementi.
rory.ap,

1
Cosa considereresti migliore: var stringhe = new string [] {}; o var stringhe = nuova stringa [0]; A proposito: considero un array vuoto un valore predefinito perfettamente valido per i parametri del metodo: public void EditItems (IEnumerable <Item> toEdit, IEnumerable <long> toDelete = new long [] {})
realbart

6
@ RickO'Shea - C ++ non è C #. Stroustrup conosce il suo C ++ - non è così sicuro di conoscere il suo C # e il GC .NET. Non entrerò in una guerra religiosa con te.
Oded,

182

Prova questo:

string[] a = new string[] { };

7
Espandendo questa risposta, puoi anche avviare l'array con elementi senza specificare la dimensione O il tipo, il compilatore inferirà dall'inizializzatore: var a = new [] {"a", "b", "c"}; Questa è ancora una matrice di stringhe fortemente tipizzata.
Nick VanderPyle

1
Eccezione non gestita: System.IndexOutOfRangeException: l'indice era al di fuori dei limiti dell'array. at ArrayClass.Main (String [] args). Ho riscontrato questo errore dopo aver modificato la mia int [] variabile = nuova int [] {}
yogesh

6
@yogesh: è strano. Quando ad esempio scrivendo int[] variable = new int[]{}e utilizzandolo ad esempio in un ciclo come foreach (var s in variable){ Console.WriteLine(s);}il codice viene compilato in: int[] args1 = new int[0];e foreach (int num in args1){Console.WriteLine(num);}. Quindi non dovrebbe esserci alcuna differenza tra l'utilizzo new int[0]e new int[]{}poiché entrambi vengono compilati con lo stesso codice.
No,

1
@GlennGordon Assolutamente, ma è nuovo dalla versione 3.0 di C # (dal 2007, con Visual Studio 2008). Questa versione consente anche un altro formato semplice con var, sebbene solo per variabili locali (non per campi). Tuttavia, in C # 2.0 (Visual Studio 2005) e versioni precedenti, è necessario utilizzare la sintassi di questa risposta (o string[] a = new string[0];).
Jeppe Stig Nielsen,

114

In .NET 4.6 il modo preferito è utilizzare un nuovo metodo Array.Empty:

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

L' implementazione è sintetica, usando come si comportano i membri statici nelle classi generiche in .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];
}

(codice relativo al contratto di codice rimosso per chiarezza)

Guarda anche:


@Cole Johnson - Grazie per la modifica, ma l'ho ripristinata. Ho omesso queste righe di proposito: volevo citare solo l'implementazione interessante. Il contratto e gli attributi del codice impediscono di capire cosa sta succedendo (il collegamento alla fonte ha tutto, ovviamente). Ho anche aggiunto una nuova riga nel commento per evitare di scorrere su Stack Overflow. Se non ti dispiace, lo preferisco così. Grazie!
Kobi,

2
Sicuramente un miglioramento per la leggibilità da:Enumerable.Empty<T>().ToArray()
DanielV

Anche se questo metodo è sicuramente preferito nella maggior parte dei casi, non risponde alla domanda originale. L'OP vuole creare un array vuoto. Array.Empty<T>()non non creare un array. Restituisce un riferimento a un array pre-allocato.
l33t

33

È possibile inizializzarlo con una dimensione pari a 0, ma sarà necessario inizializzarlo nuovamente quando si conosce la dimensione, poiché non è possibile accodarla all'array.

string[] a = new string[0];

Questa è la risposta precisa
abzarak,

7

Non ha molto senso dichiarare un array senza dimensioni. Un array ha dimensioni . Quando si dichiara un array di dimensioni specifiche, si specifica il numero fisso di slot disponibili in una raccolta che può contenere oggetti e di conseguenza viene allocata la memoria. Per aggiungere qualcosa ad esso, dovrai comunque reinizializzare l'array esistente (anche se stai ridimensionando l'array, vedi questo thread ). Uno dei rari casi in cui si desidera inizializzare un array vuoto sarebbe passare l'array come argomento.

Se vuoi definire una raccolta quando non sai di quale dimensione potrebbe essere, l'array non è la tua scelta, ma qualcosa di simile List<T>o simile.

Detto questo, l'unico modo per dichiarare un array senza specificare la dimensione è avere un array vuoto di dimensione 0 . Hemant e Alex Dn offrono due modi. Un'altra alternativa più semplice è semplicemente :

string[] a = { };

[ Gli elementi all'interno della parentesi devono essere implicitamente convertibili in un tipo definito, ad esempio,string[] a = { "a", "b" }; ]

O ancora un altro:

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

Ecco un modo più dichiarativo :

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

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

Ora puoi chiamare:

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

//or

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

1
Non riesco a pensare a nessun uso se non quando devi passare un array come parametro. Ci sono alcuni casi in riflessione in cui un metodo accetta una matrice di oggetti e potresti voler passare una matrice vuota per effettuare l'azione predefinita. Modificherò la mia risposta.
nawfal,

Ad esempio, hai un'interfaccia implementata da diverse classi che restituiscono un IEnumerable e una delle implementazioni non ha elementi per il metodo e restituisce un array vuoto, ad esempio.
Ignacio Soler Garcia,

@IgnacioSolerGarcia Vorrei restituire un array in quel caso se e solo se si tratta di un'applicazione estremamente critica per le prestazioni. Dirò che le matrici sono obsolete e dovrebbero essere evitate se possibile. Vedi questo da Lippert e questa domanda SO
nawfal

Tenere presente che il tipo restituito è IEnumerable, quindi l'array è di sola lettura e non è destinato a cambiare. Perché, ad esempio, dovrei restituire un elenco?
Ignacio Soler Garcia,

1
Un caso d'uso per un array vuoto è semplice: quando vuoi riempirlo di oggetti e non sai quanti ne aggiungerai!
vapcguy,

6

Semplice ed elegante!

string[] array = {}

Vorrei arraysolo cambiare a, come arrayè una parola chiave quando in maiuscolo. È una cattiva pratica usare un nome di parola chiave come nome di variabile, anche se il caso è diverso. E sostanzialmente la stessa della mia risposta, tranne che ho avuto String.Emptylì.
vapcguy,

1
1. array non è ac # parola chiave. L'array è una classe e non una parola chiave 2. "a" è anche una cattiva pratica (forse anche una cattiva pratica peggiore rispetto all'utilizzo delle parole chiave)
disklosr

Essere tecnici. Classe, parola chiave, definisce un tipo di oggetto ed è ancora errato. Perché pensi che asia cattivo?
vapcguy,

1
Perché i nomi delle variabili non descrittivi e di una lettera sono cattive pratiche perché non trasmettono il motivo alla base della loro definizione. "array" è sicuramente un nome migliore di "a". Un nome migliore sarebbe "emptyArray".
disklosr,

4

string[] a = new string[0];

o notazione breve:

string[] a = { };

Il modo preferito ora è:

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

Ho scritto una breve espressione regolare che puoi usare in Visual Studio se vuoi sostituire allocazioni di lunghezza zero, ad es new string[0]. Utilizzare l'opzione Trova (ricerca) in Visual Studio con l'opzione Espressione regolare attivata:

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

Ora Trova tutto o F3 (Trova successivo) e sostituisci tutto con Array.Empty <…> ()!


3

È possibile definire le dimensioni dell'array in fase di esecuzione .

Ciò ti consentirà di fare qualsiasi cosa per calcolare dinamicamente le dimensioni dell'array. Ma, una volta definita, la dimensione è immutabile.

Array a = Array.CreateInstance(typeof(string), 5);

4
Perché tutto questo? In fase di esecuzione è possibile definire normalmente la dimensione dell'array da una variabile:int i = 5; string[] a = new string[i];
Kevin Brock

Bene, immagino che con i generici questo sembri essere obsoleto.
radarbob,

2

Avevo provato:

string[] sample = new string[0];

Ma ho potuto inserire solo una stringa in esso, e quindi ho ricevuto un errore exceptionOutOfBound, quindi ho semplicemente messo una dimensione per esso, come

string[] sample = new string[100];

O un altro modo che funziona per me:

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

Assegnazione valore per elenco:

sample.Add(your input);

1

Come so non è possibile creare array senza dimensioni, ma è possibile utilizzare

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

e poi l.ToArray().


1

Combinazione dei suggerimenti di @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];
    }
}

Esempio di utilizzo:

Array<string>.Empty

AGGIORNAMENTO 2019-05-14

(crediti a @Jaider ty)

Migliore utilizzo dell'API .Net:

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

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

Si applica a:

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

...

HTH


1
In .NET Core 2, esiste già un'estensione per questo,arr = Array.Empty<string>();
Jaider

iirc, in .NetStandart [4.something] - c'è anche.
ShloEmi,

0

Tu puoi fare:

string[] a = { String.Empty };

Nota: OP significava non dover specificare una dimensione, non rendere un array privo di dimensioni


8
Questo non crea un array di stringhe di lunghezza 1?
Sumner Evans,

Vero, ma è cancellato. E OP ha chiesto di dichiarare l'array senza dover indicare una dimensione - questo si adatta a quello.
vapcguy,

E questo merita un downvote, perché? OP significava non dover avere specifyuna dimensione, non creare un array sizeless.
vapcguy,

1
@vapcguy Ero il downvoter. Me ne pento. Ho modificato la tua risposta per annullare il mio downvote. Il tuo commento rende la domanda un po 'dubbia. Non sono sicuro se questo è ciò che significava OP.
nawfal,

4
L'OP ha richiesto un array vuoto . Questo array non è vuoto.
Keith

0

Ecco un esempio del mondo reale. In questo è necessario inizializzare l'array foundFilesprima a zero lunghezza.

(Come sottolineato in altre risposte: questo inizializza non un elemento e soprattutto non un elemento con indice zero perché ciò significherebbe che l'array aveva lunghezza 1. L'array ha lunghezza zero dopo questa linea!).

Se la parte = string[0]viene omessa, si verifica un errore del compilatore!

Ciò è dovuto al blocco di cattura senza riprogrammazione. Il compilatore C # riconosce il percorso del codice, che la funzione Directory.GetFiles()può generare un'eccezione, in modo che l'array possa essere non inizializzato.

Prima che qualcuno dica, non riproporre l'eccezione sarebbe una cattiva gestione degli errori: questo non è vero. La gestione degli errori deve soddisfare i requisiti.

In questo caso, si presume che il programma debba continuare nel caso di una directory che non può essere letta e non interrotta: l'esempio migliore è una funzione che attraversa una struttura di directory. Qui la gestione degli errori lo sta semplicemente registrando. Naturalmente questo potrebbe essere fatto meglio, ad esempio raccogliendo tutte le directory con GetFiles(Dir)chiamate fallite in un elenco, ma questo porterà troppo lontano qui.

È sufficiente affermare che evitare throwè uno scenario valido e quindi l'array deve essere inizializzato su lunghezza zero. Basterebbe farlo nel blocco catch, ma questo sarebbe uno stile cattivo.

La chiamata per GetFiles(Dir)ridimensionare l'array.

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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.