1

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>?

McThrok
  • 27
  • 1
  • 8
  • 2
    "what can we do if we had that `List`?" Can you clarify this question in your posy? I do not know what you mean by this. – D Stanley Jul 27 '17 at 16:05
  • So you're trying to support other `IEnumerable` types beyond just `List`? – ryanyuyu Jul 27 '17 at 16:08
  • 4
    I think you are saying you want to declare a method that returns `K` when passed `K` - unfortunately, this cannot be done with C# generics. – Blorgbeard Jul 27 '17 at 16:10
  • 2
    You would need to use reflection to get the generic type for `K` and then `Type.MakeGenericType` to create the `` version of it. But that would be a horrible thing to do. Better to simply return `IEnumerable` and let the caller call `new Stack()` etc. with it. – Ian Mercer Jul 27 '17 at 16:38
  • 5
    Comments aside, can you please edit your question to make it clearer? As it stands, it's pretty incomprehensible what you're actually asking. – Clint Jul 27 '17 at 16:45

1 Answers1

1

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));
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179