Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why wouldn't C# support generics of generics (generics with parameterized types)?

Recently (perhaps of design shortcomings) I faced a regular task when required to have a collection of MyType<T> where T is not fixed (i.e. multiple various generics instantiations throughout one collection).

As it's widely proposed (for such cases) an abstract class was declared:

public abstract class MyType {}
public class MyType<T>: MyType {}

and then I'm having a collection of MyType. However for this collection I had a constraint of having no more than one element for any type T.

Hence, I made a bit of custom implementation of ICollection<TBase>. I wanted to include there a method Get<TParam>() for getting an item corresponding to type TParam. To be later used like:

MyCollection<MyType> collection = new MyCollection<MyType>();
MyType<int> myInt = collection.Get<int>();

However I unexpectedly discovered that I can't even declare it:

public TCustom<TParam> Get<TParam, TCustom<TParam>>() { } //this won't compile

because inner generics (or so-called "generics of generics") are neither supported by C# nor by .NET (I suppose). How do you think, were there any specific reasons behind such limitations (except for complexity)?

UPDATE 1. Asked for compiler version and compiler errors.

Microsoft C#, .NET 3.5 (Visual Studio 2010). Errors:

error CS0081: Type parameter declaration must be an identifier not a type

error CS0246: The type or namespace name 'TCustom' could not be found (are you missing a using directive or an assembly reference?)

UPDATE 2. Asked whether I need a fix or explanations why. I really wanna know WHY. But if you have good solutions to the problem, you are also welcome.

UPDATE 3. The question might be answered already in this blog post. It appears that CLR team was under big pressure not to overcomplicate the language.

like image 745
Alec Avatar asked Nov 14 '22 16:11

Alec


1 Answers

In this case you could simply hide the data in a non-generic dictionary:

private Dictionary<Type, object> _Data;

and then your Get method:

public MyType<TParam> Get<TParam>()
{ 
    return (MyType<TParam>)_Data[typeof(TParam)];
}

If the TParam types aren't related, there is no common data structure that will give you type-safety anyway, so why even try?

like image 81
Lasse V. Karlsen Avatar answered Apr 26 '23 17:04

Lasse V. Karlsen