2010-01-22 25 views
31

Quali sono i pro/contro dell'uso della parola chiave params rispetto a una lista come input per qualche funzione C#?C#: parola chiave params vs. lista

Principalmente quali sono le prestazioni considerazioni e altre compensazioni.

risposta

33

La parola chiave params è zucchero sintattico gestito dal compilatore C#. sotto il cofano, in realtà è svolta

void Foo(params object[] a) { ... } 
Foo(1,2,"THREE"); 

in

void Foo(object[] a) { ... } 
Foo(new object[] { 1, 2, "THREE" }) 

Da un prospettiva prestazioni come si sta chiedendo, la chiamata params è semplicemente più veloce, perché è un po 'più veloce per creare un array piuttosto che creare un elenco <>. Non c'è differenza di prestazioni tra i due frammenti sopra.

+0

Se si passasse un riferimento List esistente, sarebbe più lento utilizzare params a causa del sovraccarico di allocazione della memoria per l'array. –

+1

@Mert: Ma hai anche dovuto allocare memoria per la lista <> che stai passando come riferimento ... –

+0

@ZeCarlos, ma ho dato per scontato che la Lista fosse già "esistente". –

2

La parola chiave params consente di passare in modo dinamico un numero variabile di argomenti della funzione, senza preoccuparsi di errori del compilatore come questo:

public string PrefixFormatString(string p, string s, params object[] par) 
{ 
    return p + string.Format(s, par); 
} 
... 
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", errNum, errStr); 

Se si passa una lista, si deve costruire l'elenco prima di poter passarlo in:

public string PrefixFormatString(string p, string s, List<object> par) 
{ 
    return p + string.Format(s, par.ToArray()); 
} 
... 
List<object> l = new List<object>(new object[] { errNum, errStr }); 
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", l); 

e tende a nascondere il significato di quale tipo di dati della funzione aspettava.

Si noti che questo è molto simile al passaggio di una semplice variabile di matrice. L'unica differenza è che il compilatore sistemerà i parametri in un array per te ... Non sono sicuro al 100%, ma penso che la differenza tecnica sia solo lo zucchero sintattico - in entrambi i casi stai passando davvero una serie di digitare il parametro è.

+0

quanto sui problemi di prestazioni? –

+2

Questo non è il tipo di problema che dovresti davvero preoccuparti delle prestazioni: sono sicuro che ci sono problemi di hogging delle prestazioni molto più grandi in qualsiasi cosa tu stia considerando. La performance è praticamente la stessa, a causa del fatto (penso) che si tratta principalmente di una sintassi del compilatore e non ha nulla a che fare con il modo in cui la funzione stessa viene chiamata una volta che è in IL. –

0

Bene, con i params parola chiave che potrebbe inserire dei parametri in un metodo come questo:

MethodName(1, 2, 3, 4); 

Ma con una lista, si farebbe in questo modo:

MethodName(new List<int> {1, 2, 3, 4}); 

La sintassi può essere un po 'più chiaro nel primo rispetto al secondo. Questo è utile quando v'è solo un parametro da passare:

// params 
MethodName(1); 

// List 
MethodName(new List<int> {1}); 
+0

per quanto riguarda i problemi di prestazioni? –

2

Ebbene, il params consente una sintassi più bello quando si chiama, ma la lista (supponendo che si intende IList<>) è più flessibile perché le classi differenti possono attuare l'interfaccia. Il passaggio a List<> ha senso solo se è necessario eseguire operazioni specifiche nell'elenco che non sono supportate dall'interfaccia (come ToArray()).

+0

per quanto riguarda i problemi di prestazioni? –

+0

E riguardo a loro? –

+0

+1 per IList o qualsiasi altra interfaccia pertinente a seconda di ciò che la raccolta deve fare. –

0

params è un linguaggio costrutto per funzioni che richiedono un numero variabile di parametri. È simile allo specificatore di C elipses, ad esempio printf(char* fmt, ...). Il linguaggio supporta questo tipo di operazione, potrebbe anche usarlo, specialmente se rende il codice più facile da leggere.

0

Personalmente, vorrei saltare i parametri. Sono stato morso da esso una o due volte. Come? Lasciatemi spiegare.

si scrive un metodo pubblico con questa firma:

public static void LogInUser(string username, string password, params string[] options) 

si prova, funziona, il suo fatto ... e un altro di montaggio/applicazione chiama la funzione.

Ora, un mese più tardi si desidera cambiare la vostra firma per aggiungere ruolo utente:

public static void LogInUser(string username, string password, string role, params string[] options) 

Oh come le cose sono cambiate per niente chiamare il metodo.

LogInUser("[email protected]", "zz", "Admin", "rememberMe", "800x600"); 
+0

Inoltre, i parametri "odori" come usato frequentemente per Interop. –

+4

Beh, non avresti quel problema se hai raggruppato i membri definiti in un singolo oggetto, come "Credenziali". –

+1

Dynami, hai assolutamente ragione. Cattivo codice ... cattivo uso dei param. –

0

La differenza principale tra i due che posso vedere è che il numero di parametri passati nel metodo è impostata al momento della compilazione usando params, mentre con un List<T> dipende lista passata in fase di esecuzione.

Se il problema di fissare il numero di argomenti con cui il metodo deve essere richiamato al momento della compilazione è un pro o un controllo dipende interamente dal progetto e dall'intento. O può essere un vantaggio a seconda di ciò che speri di ottenere.

Params aiuta sul fronte della leggibilità ed è il più vicino possibile a un parametro facoltativo che si otterrà in C#. Utilizzerei personalmente l'implementazione List<T> solo se avessi bisogno di consumare un numero sconosciuto di parametri in qualsiasi momento.

Modifica: è stata individuata la modifica relativa ai problemi di prestazioni. Su questo argomento non sono sicuro, anche se potreste potenzialmente aspettarvi un gran numero di "parametri" usando List<T>, mentre params ha un limite di integrità a causa del fatto che devono essere codificati.

23

personalmente utilizzo params quando crei funzioni che richiedono un numero di ingressi fornite da altro programmatore (per esempio String.Format), e IEnumerable quando si scrive funzioni che richiedono un elenco di elementi di dati fornito dal computer (ad esempio File.Write).

Le implicazioni sulla performance sono trascurabili. Preoccuparsi delle prestazioni di una cosa banale come questa è esattamente di cui parlava Donald Knuth nella famosa citazione "ottimizzazione prematura è la radice di tutti i mali".

Detto questo, il richiedente sembra essere fissata su di esso, in modo da qui si va:

Risultati per 10 milioni di iterazioni:

params took 308 ms 
list took 879 ms 

Da questi risultati possiamo vedere che l'array params è solo oltre il doppio della velocità. Il semplice fatto che puoi chiamare una di queste cose Dieci milioni di volte in meno di un secondo significa che stai completamente sprecando il tuo tempo preoccupandoti. Usa quello che meglio si adatta al tuo codice.

Il codice di provarlo (compilato ed eseguito in modalità di rilascio utilizzando VS2008)

class Program 
{ 
    const int COUNT = 10000000; 

    static IEnumerable<string> m_value = null; 

    static void ParamsMethod(params string[] args) 
    { m_value = args; } // do something with it to stop the compiler just optimizing this method away 

    static void ListMethod(List<string> args) 
    { m_value = args; } // do SOMETHING with it to stop the compiler just optimizing this method away 

    static void Main(string[] args) 
    { 
     var s = new Stopwatch(); 
     s.Start(); 
     for (int i = 0; i < COUNT; ++i) 
      ParamsMethod("a", "b", "c"); 

     Console.WriteLine("params took {0} ms", s.ElapsedMilliseconds); 

     s.Reset(); 
     s.Start(); 
     for (int i = 0; i < COUNT; ++i) 
      ListMethod(new List<string> { "a", "b", "c" }); 

     Console.WriteLine("list took {0} ms", s.ElapsedMilliseconds); 
    } 
} 
+0

Ecco perché il tempo di creazione della lista è lento. se chiami un metodo che accetta IEnumerable con dire, una stringa [] invece di una lista , la prestazione sarebbe quasi equivalente al metodo params. – Jimmy

+10

Sicuro, ma non importa! –

0

Le prestazioni del programmatore che chiamano il metodo a volte possono essere migliorate dai vostri utilizzi della parola chiave params.

(Dato che i programmatori costano molto di più di computer, perché stai pensando di qualsiasi altro tipo di prestazioni.)