2010-01-22 5 views
31

Quels sont les avantages/inconvénients de l'utilisation du mot-clé params par rapport à une liste en tant qu'entrée pour une fonction C#?C#: params mot-clé vs liste

Principalement qu'est ce que le performance et d'autres compromis.

Répondre

33

Le mot-clé params est le sucre syntaxique géré par le compilateur C#. sous le capot, il tourne en fait

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

dans

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

d'une performance perspective comme vous demandez au sujet, l'appel params est tout simplement plus rapide car il est un peu plus rapide pour créer un tableau que pour créer une liste <>. Il n'y a pas de différence de performance entre les deux extraits ci-dessus.

+0

Si nous passions une référence List existante, il serait plus lent d'utiliser des params en raison de la surcharge de l'allocation de mémoire pour array. –

+1

@Mert: Mais vous deviez aussi allouer de la mémoire pour la liste <> que vous passez en référence ... –

+0

@ZeCarlos, mais j'ai supposé que la liste existait déjà. –

2

Le mot-clé params vous permet de passer dynamiquement un nombre variable d'arguments à la fonction sans se soucier des erreurs du compilateur comme celui-ci:

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); 

Si vous passez une liste, vous devez construire la liste avant de pouvoir passer le:

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); 

et il tend à cacher la signification du type de données que la fonction attend.

Notez que cela est très similaire au passage d'une variable tableau simple. La seule différence est que le compilateur va fixer les paramètres dans un tableau pour vous ... Je ne suis pas sûr à 100%, mais je pense que la différence technique est juste du sucre syntaxique - dans les deux cas, vous passez vraiment un tableau de tapez le paramètre est.

+0

Qu'en est-il des problèmes de performance? –

+2

Ce n'est pas le type de problème que vous devriez vraiment vous préoccuper de la performance - je suis sûr qu'il y a beaucoup plus de problèmes de performance dans tout ce que vous envisagez. La performance est pratiquement la même, à cause du fait (je pense) que c'est principalement une syntaxe de compilateur, et n'a rien à voir avec la façon dont la fonction elle-même est appelée une fois dans IL. –

0

Eh bien, avec le mot-clé params vous pouvez entrer des arguments dans une méthode comme ceci:

MethodName(1, 2, 3, 4); 

Mais avec une liste, vous feriez comme ceci:

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

La syntaxe peut être un peu plus clair dans le premier que dans le dernier. Ceci est utile lorsque vous avez juste un paramètre à passer:

// params 
MethodName(1); 

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

qu'en est-il des problèmes de performances? –

2

Eh bien, le params permet une plus belle syntaxe lors de l'appel, mais la liste (en supposant que vous dire IList<>) est plus souple car les différentes classes peuvent mettre en œuvre L'interface. Passer un List<> n'a de sens que si vous devez effectuer des opérations spécifiques sur la liste qui ne sont pas supportées par l'interface (par exemple ToArray()).

+0

qu'en est-il des problèmes de performances? –

+0

Et à propos d'eux? –

+0

+1 pour IList , ou toute autre interface pertinente en fonction de ce que votre collection doit faire. –

0

params est une construction de langage pour des fonctions prenant un nombre variable de paramètres. Il est similaire au spécificateur C elipses - c'est-à-dire printf(char* fmt, ...). Le langage supporte ce genre d'opération, pourrait aussi bien l'utiliser, surtout s'il rend le code plus facile à lire.

0

Personnellement, je passerais les params. J'ai été mordu par une ou deux fois. Comment? Laisse-moi expliquer.

Vous écrivez une méthode publique avec cette signature:

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

Vous testez, cela fonctionne, le fait ... et un autre ensemble/application appelle votre fonction.

Maintenant, un mois plus tard que vous voulez changer votre signature pour ajouter le rôle de l'utilisateur:

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

Oh comment les choses ont changé quoi que ce soit d'appeler votre méthode.

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

En outre, les params "sent" comme il a souvent utilisé pour Interop. –

+4

Eh bien, vous n'auriez pas ce problème si vous groupiez vos membres définis dans un seul objet, comme 'Credentials'. –

+1

Dynami, vous avez absolument raison. Mauvais code ... mauvaise utilisation des params. –

0

La principale différence entre les deux que je vois est que le nombre de paramètres transmis dans le procédé est défini lors de la compilation en utilisant params, alors qu'avec un List<T> elle dépend de la liste dans le passé à l'exécution.

Si la définition du nombre d'arguments auxquels votre méthode doit être appelée au moment de la compilation est un pro ou un con dépend entièrement de votre conception et de votre intention. Soit peut être un avantage en fonction de ce que vous espérez réaliser. Aide à la lisibilité, et est aussi proche d'un paramètre facultatif que vous allez obtenir en C#. Je n'utiliserais personnellement la mise en œuvre List<T> si j'avais besoin de consommer un nombre inconnu de paramètres à tout moment.

Modifier: juste repéré votre modification concernant les problèmes de performance. Sur ce sujet, je ne suis pas sûr, mais si vous pouvez potentiellement attendre un grand nombre de «paramètres» en utilisant List<T>, tandis que params a un plafond de raison, car ils doivent être codés.

23

personnellement j'utiliser params lors de l'écriture des fonctions qui prennent un certain nombre d'entrées fournies par un autre programmeur (par exemple String.Format), et IEnumerable lors de l'écriture des fonctions qui prennent une liste d'éléments de données fournis par l'ordinateur (par exemple File.Write).

Les implications sur les performances sont négligeables. S'inquiéter de la performance d'une chose triviale comme ceci est exactement ce dont Donald Knuth parlait dans la célèbre citation "l'optimisation prématurée est la racine de tous les maux".

Cela dit, le demandeur semble être obsédé par elle, alors là, vous allez:

Résultats pour 10 millions d'itérations:

params took 308 ms 
list took 879 ms 

A partir de ces résultats, nous pouvons voir que le tableau params est juste plus de deux fois plus vite. Le simple fait que vous pouvez appeler l'une de ces choses dix millions de fois en moins d'une seconde signifie que vous perdez complètement votre temps en vous inquiéter à ce sujet. Utilisez ce qui convient le mieux à votre code.

Le code pour le tester (compilé et exécuté en mode de libération en utilisant 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

En effet, la création de la liste est lente. si vous appelez une méthode qui prend IEnumerable avec say, une chaîne [] au lieu d'une liste la performance serait presque équivalente à la méthode params. – Jimmy

+10

Bien sûr, mais ce n'est pas grave! –

0

Les performances du programmeur appelant votre méthode peuvent parfois être améliorées par vos utilisations du mot-clé params.

(Étant donné que les programmeurs coûtent tellement plus alors les ordinateurs, pourquoi pensez-vous de tout autre type de performance.)