J'ai récemment appris que vous pouvez créer une méthode avec des paramètres illimités, par exemple:
SomeMethod(params int[] numbers);
mais ma question est, quelle est la différence entre cela et simplement créer une méthode qui reçoit une liste ou un tableau?
SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);
peut-être que cela a un impact sur les performances? Je ne comprends pas complètement ou ne vois pas en quoi vous préféreriez celui avec des paramètres illimités.
Une recherche rapide sur google n'a pas aidé, j'espère que vous pourrez m'aider.
params
également que le type de l'argument soit un tableau. Si vous devez consommer une collection autre qu'un tableau, il peut être plus judicieux de fournir un non-params
argument à la place.Console.Write
.Réponses:
La différence entre
et
est que M peut être appelé comme ceci:
ou comme ça:
mais N ne peut être appelé que de la deuxième manière, pas de la première .
L'impact sur les performances est que, que vous appeliez
M
de la première ou de la deuxième manière, de toute façon, vous créez un tableau. La création d'une baie a un impact sur les performances car elle prend du temps et de la mémoire. N'oubliez pas que les impacts sur les performances doivent être mesurés par rapport aux objectifs de performances; il est peu probable que le coût de la création d'une baie supplémentaire soit le facteur de déclenchement qui fait la différence entre le succès et l'échec sur le marché.C'est purement et entièrement une commodité pour l'auteur du code qui appelle la méthode; il est simplement plus court et plus facile à écrire
au lieu d'écrire
Il enregistre simplement quelques touches du côté de l'appelant. C'est tout.
Quelques questions que vous n'avez pas posées mais que vous souhaiteriez peut-être connaître:
Les méthodes qui permettent de passer un nombre variable d'arguments du côté de l'appelant sont appelées variadic . Les méthodes params sont la façon dont C # implémente les méthodes variadiques.
Lorsqu'il est confronté à un problème de résolution de surcharge, C # considérera les formulaires "normal" et "étendu", et le formulaire "normal" l'emportera toujours si les deux sont applicables. Par exemple, considérez ceci:
et nous avons un appel
Il y a deux possibilités applicables. Sous forme "normale", nous appelons
P
et passons une référence nulle pour le tableau. Sous forme "élargie", nous appelonsP(new object[] { null })
. Dans ce cas, la forme normale l'emporte. Si nous avons eu un appel,P(null, null)
le formulaire normal est inapplicable et le formulaire étendu gagne par défaut.Défi : Supposons que nous ayons
var s = new[] { "hello" };
un appelP(s);
. Décrivez ce qui se passe sur le site de l'appel et pourquoi. Vous pourriez être surpris!Défi : Supposons que nous ayons les deux
void P(object x){}
etvoid P(params object[] x){}
. Que faitP(null)
et pourquoi?Défi : Supposons que nous ayons les deux
void M(string x){}
etvoid M(params string[] x){}
. Que faitM(null)
et pourquoi? En quoi cela diffère-t-il du cas précédent?la source
P(null)
vsP((object)null)
vsP((object[])null)
- où puis-je trouver une explication à cette différence? On se sent commenull
eu un certain type spécial , qui se transforme en tableau plutôt que l' objet (P(null)
), mais trouver la conversion en chaîne ou un tableau de chaînes ambiguës (M(null)
) ... qui se sent très étrange, s'attendre que ce soit soit ambiguë dans les deux cas ou choisir la version à un seul argument (ce qui n'est pas le cas). Mais je suppose qu'il s'agit davantage d'params
être générique , comme la référence universelle (&&
) dans les modèles C ++, et donc une meilleure correspondance (dans Ch2, pas dans Ch3).object[]
sontobject
, mais tous neobject
sontobject[]
doncobject[]
plus spécifique.string[]
sontstring
». En fait, NOstring[]
arestring
et NOstring
arestring[]
,string
n'est donc pas plus spécifique ou plus général questring[]
, et nous obtenons une erreur d'ambiguïté lorsqu'on nous demande de choisir.object[]
sontobject
...object[]
est plus spécifique, il enP(null)
va de même pour le tableau plus spécifique, thx, c'est ce qui me manquait. Trouvé quelques règles ici: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…Je viens de faire un petit prototype. La réponse semble être
params
simplement du sucre syntaxique pour passer dans un tableau. Ce n'est pas vraiment une surprise. J'ai créé deux versions de la même méthode, où la seule différence est le mot-clé "params". L'IL généré pour les deux était identique, sauf qu'un aSystem.ParamArrayAttribute
était appliqué à laparams
version.De plus, l'IL généré sur le site d'appel était également le même entre moi appelant la méthode avec un déclaré manuellement
new int[]
et appelant la méthode en utilisant simplement lesparams
arguments.Ainsi, la réponse semble être "commodité". Il ne semble pas y avoir de différence de performances. Vous pouvez également appeler une
params
fonction avec un tableau à la place, ce n'est donc pas très surprenant. Cela revient à dire s'il est plus facile pour le consommateur de votre méthode de l'appeler avec n'importe quel nombre de paramètres (par exemplesomeMethod(1, 2, 3)
) que d'avoir toujours à créer une collection en premier (par exemplesomeMethod(new List<int>() { 1, 2, 3 } )
).la source
La fonctionnalité de paramètres illimités offre les avantages suivants dans de nombreux scénarios:
Voici un exemple où l'option de paramètres illimités est un excellent choix
Considérez qu'une application d'envoi d'emails doit être construite.
La fonction qui envoie l'e-mail doit pouvoir gérer une ou plusieurs valeurs pour les champs «À», «CC» et «BCC».
Si les types de paramètres sont fixés pour être des tableaux ou des listes pour tous les champs (To, CC, BCC), alors la fonction appelante sera forcée de gérer toute la complexité de la définition de 3 tableaux ou listes afin d'appeler la fonction expéditeur d'e-mail .
Même si l'appelant souhaite envoyer un e-mail à une seule adresse, la fonction d'expéditeur d'e-mail forcera l'appelant à définir et envoyer 3 tableaux différents en tant que paramètres.
Si la fonction expéditeur d'e-mails adopte l'approche des paramètres illimités, la fonction appelant n'a pas besoin de gérer toute la complexité.
L'approche des paramètres illimités contribue à une meilleure performance d'exécution de l'application en évitant la création de tableaux ou de listes là où cela n'est pas nécessaire.
la source
Du point de vue des performances et du style, le
params
mot-clé est vraiment agréable à avoir lorsque vous souhaitez envoyer une liste de paramètres facultative.Personnellement, j'utilisais
params
quand mon code était quelque chose commeLa bonne partie à ce sujet est que je peux utiliser cette méthode partout sans avoir à créer un tableau ou une liste à chaque fois.
J'utiliserais
array
oulist
quand je sais que je passerai toujours cette fonction un ensemble de données qui est déjà mis en place commeJe vois l'avantage de
params
la flexibilité qu'il ajoute. Cela peut avoir un impact relativement mineur sur votre code, mais c'est toujours un bon outil à avoir.la source
La convention d'appel est différente. Par exemple ...
Dans le premier cas, vous pouvez passer autant d'entiers que de paramètres distincts à la méthode. Dans le second, vous devrez instancier une liste et la transmettre.
la source