Reputation: 27
Let's assum that we have this function:
List<string> ToCollectionString<T>(List<T> collectinon);
and now how can we change List
to return specific IEnumerable
the same as given argument? We get List
so return List
, we get Stack
so return Stack
etc.
If we had:
List<T> ToCollectionString<T>(List<T>);
it would be
K ToCollectionString<K,T>(K collection) where K:IEnumerable<T>
But what can we do if we had that List<string>
?
Upvotes: 1
Views: 97
Reputation: 100547
Assuming you are trying to create instance of the same collection type that was passed in but holding strings.
In general this is not possible as type passed in may not have a way to construct new instance of the type based on information you have (obvious case - result of list.Select(...)
passed as argument - type implementing it does not have visible constructor).
In somewhat rare cases when you can construct type you'd have to use reflection to find exact type of argument, Using C# reflection to call a constructor. If you need empty collection - you are done at this point.
If you need to add items to the resulting collection (i.e. you wanted to call "ToString" on each source item) if you need either find clone constuctor with IEnumerable
as argument you re in luck, otherwise you'd have to populate resulting collection (possibly with reflection - How to use reflection to add a new item to a collection). If you can limit incoming types to something that support an interface with "add item" functionality (i.e. IList
) at least second part can be strongly typed.
Note: it may be easier and more useful to just return IEnumerable<string>
(i.e. return collection.Select(x=>x.ToString())
and let caller to construct correct type - this way you avoid all reflection complexity and let caller to use strongly typed values instead of casting result. It will also avoid cases when type can't be constructed as caller is responsible for it:
var stronglyTyped = new Stack(ToCollectionString(collectinon));
Upvotes: 1