web-dev-qa-db-fra.com

Paramètres IEnumerable <T> c #

Pourquoi ne puis-je pas utiliser un IEnumerable avec des paramètres? Cela sera-t-il jamais réglé? Je souhaite vraiment qu'ils réécrivent les anciennes bibliothèques pour utiliser des génériques ...

60
Dested

Pourquoi ne puis-je pas utiliser un IEnumerable avec des paramètres?

La question présuppose que l'équipe de conception doit fournir une raison pour ne pas ajouter une fonctionnalité au langage. Cette présupposition est fausse.

Au contraire, pour qu'une fonctionnalité soit utilisée par vous, elle doit être pensée, conçue, spécifiée, implémentée, testée, documentée et expédiée. Tous ces éléments ont des coûts élevés.

La fonction "params enumerable" a été pensée et conçue. Il n'a jamais été spécifié, implémenté, testé, documenté ou expédié.

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


MISE À JOUR: Au moment d'écrire ces lignes - début 2015 - a maintenant été spécifié, mais l'implémentation, les tests, la documentation et l'expédition ont été coupés pour C # 6.0 à la fin de 2014. Voir l'annonce de Lucian ici: http: // roslyn.codeplex.com/discussions/56882 .

Comme il n'a toujours pas été implémenté, testé, documenté et expédié, il n'existe toujours pas de telle fonctionnalité. Espérons que cela en fera une future version hypothétique de C #.


MISE À JOUR: Je devrais clarifier ce que j'entends par "la fonctionnalité" car il est possible que nous ayons tous des idées différentes dans nos têtes ce que "la fonctionnalité" est. La fonctionnalité dont je parle est de vous permettre de dire quelque chose comme

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

puis le site d'appel peut être soit sous la "forme normale" de passage d'une séquence d'entiers, soit sous la "forme développée" de Frob (10, 20, 30). Si dans la forme développée, le compilateur génère l'appel comme si vous aviez dit Frob (new int [] {10, 20, 30}), comme il le fait pour les tableaux de paramètres. L'intérêt de cette fonctionnalité est qu'il arrive souvent que la méthode n'utilise jamais d'accès aléatoire au tableau, et par conséquent, nous pourrions affaiblir l'exigence selon laquelle les paramètres doivent être un tableau. Les paramètres pourraient être simplement une séquence à la place.

Vous pouvez le faire aujourd'hui en effectuant 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 pénible. Nous pourrions simplement vous permettre d'utiliser IEnumerable comme type d'argument params et en finir avec lui.

Cela sera-t-il jamais réglé?

J'espere. Cette fonctionnalité est sur la liste depuis longtemps. Cela permettrait à de nombreuses fonctions de fonctionner beaucoup plus bien avec LINQ.

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

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

Cependant, il s'agit d'une simple fonction de "petite commodité"; cela n'ajoute pas vraiment beaucoup de puissance nouvelle à la langue. C'est pourquoi il n'a jamais été suffisamment élevé dans la liste des priorités pour atteindre le stade "la spécification est écrite".

Je souhaite vraiment qu'ils réécrivent les anciennes bibliothèques pour utiliser des génériques.

Commentaire noté.

92
Eric Lippert

Ah, je pense que je peut maintenant compris ce que vous voulez dire. Je pense que vous voulez pouvoir déclarer une méthode comme celle-ci:

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

Et puis être capable de l'appeler avec un argument "normal" comme celui-ci:

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

ou avec plusieurs paramètres comme celui-ci:

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

C'est ce que vous recherchez? (En notant que vous souhaitez que le premier formulaire utilise T=string, plutôt que T=IEnumerable<string> avec un seul élément ...)

Si oui, je suis d'accord pourrait être utile - mais c'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 fais cela assez souvent pour faire de ce qui précède une solution de contournement particulièrement laide.

Notez que lors de l'appel du code ci-dessus, vous voudrez explicitement spécifier l'argument type, pour éviter que le compilateur ne préfère l'exemple params. Donc par exemple:

List<string> x = new List<string>();
Foo<string>(x);
12
Jon Skeet

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

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

TheMethod(theIEnumerable.ToArray());
4
Guffa