60 votes

Paramètres IEnumerable <T> c #

Pourquoi ne puis-je pas utiliser un IEnumerable avec params? Cela changera-t-il à l'avenir?

97voto

Eric Lippert Points 300275

Pourquoi ne puis-je pas utiliser un IEnumerable avec params?

Pour qu'une fonction soit utilisée par vous, il doit être pensé, conçu, a précisé, mise en œuvre, testé, documenté et expédiés.

Le "params énumérable" a été pensé et conçu. Il n'a jamais été spécifié, mise en œuvre, testé, documenté ou expédiés.

Par conséquent, vous ne pouvez pas utiliser la fonction.

Mise à JOUR: je me dois de préciser ce que j'entends par "la fonction" puisque c'est possible, nous avons tous des idées différentes dans nos têtes que "la fonctionnalité" est. La fonctionnalité que je suis en train de parler de vous permettre de dire quelque chose comme

void Frob(params IEnumerable<int> x)
{
    foreach(int y in x) ...
}

et puis le site d'appel peut être soit dans la "forme normale" de passer d'une séquence d'entiers, ou de la "forme élargie" de Frob(10, 20, 30). Si dans la forme développée, le compilateur génère l'appel comme si vous avais dit Frob(new int[] { 10, 20, 30}), de la même façon que pour les param tableaux. Le point de la caractéristique est qu'il est souvent le cas que la méthode n'utilise jamais l'accès aléatoire à la matrice, et par conséquent, on pourrait affaiblir l'exigence que les params être un tableau. Les params pourrait être simplement une séquence à la place.

Vous pouvez le faire aujourd'hui en faisant une surcharge:

void Frob(params int[] x) { Frob((IEnumerable<int>)x); }

void Frob(IEnumerable<int> x)
{
    foreach(int y in x) ...
}

ce qui est un peu de douleur. Nous pourrions tout simplement vous permettre d'utiliser IEnumerable comme le type de la params argument et être fait avec elle.

Sera-ce jamais être corrigé?

Je l'espère. Cette fonctionnalité a été sur la liste pendant une longue période. Il ferait beaucoup de fonctions de travail beaucoup plus parfaitement avec LINQ.

Frob(from c in customers select c.Age);

sans avoir à écrire deux versions différentes de Frob.

Cependant, il est un simple "petit confort" caractéristique; il ne fait pas ajouter tout un tas de nouveau pouvoir de la langue. C'est pourquoi il n'est jamais assez haut sur la liste de priorité pour se rendre à la "spécification est écrit" la scène.

Je souhaite vraiment que de la réécrire les anciennes bibliothèques à l'utilisation des génériques.

Commentaire noté.

11voto

Jon Skeet Points 692016

Ah, je pense que je peut maintenant avoir compris ce que tu veux dire. Je pense que vous voulez être en mesure de déclarer une méthode comme ceci:

public void Foo<T>(params IEnumerable<T> items)
{
}

Et ensuite être capable de l'appeler avec un "normal" argument comme ceci:

IEnumerable<string> existingEnumerable = ...;
Foo(existingEnumerable);

ou avec plusieurs paramètres comme ceci:

Foo("first", "second", "third");

Est-ce que vous êtes après? (À noter que vous voudriez la première forme d'utilisation T=string, plutôt que d' T=IEnumerable<string> avec un seul élément...)

Si oui, je suis d'accord, il pourrait être utile - mais il est assez facile d'avoir:

public void Foo<T>(params T[] items)
{
    Foo((IEnumerable<T>) items);
}

public void Foo<T>(IEnumerable<T> items)
{
}

Je ne trouve pas que je le fais assez souvent pour faire le dessus d'une particulièrement laid solution de contournement.

Notez que lors de l'appel le code ci-dessus, vous devrez explicitement spécifier le type d'argument, pour éviter que le compilateur préférant l' params exemple. Ainsi, par exemple:

List<string> x = new List<string>();
Foo<string>(x);

4voto

Paolo Moretti Points 9519

Selon la fonctionnalité du langage état de la mise en page de la Roslyn projet, ce qui est prévu pour être mis en œuvre dans les prochaines versions de C# (probablement en C# 6.0).

Donc, vous n'avez plus besoin de définir vos paramètres de méthodes comme un tableau et en vigueur au début de l'évaluation des arguments:

Avant

Do(values.ToArray());
...
public void Do(params int[] values) { ... }

Après

Do(values);
public void Do(params IEnumerable<Point> points) { ... }

4voto

Guffa Points 308133

Les paramètres params sont envoyés en tant que tableau et un IEnumerable<T> ne fournit pas l'accès aléatoire requis pour agir en tant que tableau.

Vous devez créer le tableau à partir de IEnumerable lorsque vous appelez la méthode:

 TheMethod(theIEnumerable.ToArray());
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X