2017-07-27 10 views
1

Regardons les choses en assum que nous avons cette fonction:spécifique IEnumerable <T> à IEnumerable spécifique <string>

List<string> ToCollectionString<T>(List<T> collectinon); 

et maintenant comment pouvons-nous changer List retourner spécifique IEnumerable le même argument donné? Nous obtenons donc retourner ListList, nous obtenons Stack donc retourner Stack etc.

Si nous avions:

List<T> ToCollectionString<T>(List<T>); 

il serait

K ToCollectionString<K,T>(K collection) where K:IEnumerable<T> 

Mais que pouvons-nous faire si nous avions cette List<string> ?

+2

« que pouvons-nous faire si nous avions cette' 'Liste ? » pouvez-vous clarifier cette question dans votre posy? Je ne sais pas ce que vous voulez dire par là: –

+0

Donc vous essayez de supporter d'autres types 'IEnumerable' au-delà juste 'List'? – ryanyuyu

+4

Je pense que vous dites que vous voulez déclarer une méthode qui renvoie 'K ' lorsqu'il est passé 'K ' - malheureusement, cela ne peut pas être fait avec les génériques C#. – Blorgbeard

Répondre

1

En supposant que vous essayez de créer une instance du même type de collection qui a été transmise mais contenant des chaînes.

En général, ce n'est pas possible car le type transmis ne peut pas construire une nouvelle instance du type basé sur les informations que vous avez (cas évident - résultat de list.Select(...) passé en argument - type implémentant n'a pas de constructeur visible).

Dans des cas assez rares où vous pouvez construire un type, vous devez utiliser la réflexion pour trouver le type exact d'argument, Using C# reflection to call a constructor. Si vous avez besoin d'une collection vide, vous avez terminé à ce stade. Si vous avez besoin d'ajouter des éléments à la collection résultante (c'est-à-dire que vous vouliez appeler "ToString" sur chaque élément source) si vous avez besoin de find clone constuctor avec IEnumerable comme argument vous avez de la chance, sinon vous devrez remplir la collection résultante (éventuellement avec réflexion - How to use reflection to add a new item to a collection). Si vous pouvez limiter les types entrants à quelque chose qui prend en charge une interface avec la fonctionnalité "ajouter un élément" (c'est-à-dire IList), au moins une deuxième partie peut être fortement typée.


Note: il peut être plus facile et plus utile de revenir juste IEnumerable<string> (c.-à-return collection.Select(x=>x.ToString()) et laisser l'appelant pour construire le type correct - Vous éviterez ainsi toute la complexité de la réflexion et de laisser l'appelant d'utiliser des valeurs fortement typées au lieu de résultat casting . il permettra également d'éviter des cas lorsque le type ne peut pas être construit comme appelant en est responsable:

var stronglyTyped = new Stack(ToCollectionString(collectinon));