5

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.

Community
  • 1
  • 1
Alec
  • 1,486
  • 2
  • 14
  • 30
  • 1
    please also add the compiler error you're getting – mtijn Oct 07 '11 at 09:24
  • This can only be answered by the C# Team at Microsoft. If you're lucky one of them will see this Q, but really this isn't the kind of question that SO works with: you're asking for an opinion. – Richard Oct 07 '11 at 09:24
  • Are you asking *why* this is a limitation (and I'm not entirely sure I understand what you want to begin with, it was quite convoluted the scenario you described here), or *how* to fix this? – Lasse V. Karlsen Oct 07 '11 at 10:17
  • Lasse, I am pretty sure it can't be fixed without deeper redesign. Hence I will appreciate any good solutions, but I am more interested why, perhaps Microsoft kept smth on its mind when limiting this. – Alec Oct 07 '11 at 10:22
  • It would be helpful if you could put together a short but complete code sample that illustrates the error. As it is, I can't determine what your `TCustom` class is supposed to be, so I'm at a bit of a loss trying to figure out what exactly you're trying to do. – Jim Mischel Oct 07 '11 at 14:53
  • Jim, nothing special about this type. TCustom<> is supposed to be MyType<>. – Alec Oct 08 '11 at 08:41

2 Answers2

1

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?

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • A type-safe approach for newer versions of .NET would be to have a static class `MyTypeDataHolder where T:class` which contains a `ConditionalWeakTable` Then `MyType Get` could fetch data from `MyTypeDataHolder.table[this]`. – supercat Dec 10 '13 at 17:50
0

Why exactly do you need

public TCustom<TParam> Get<TParam, TCustom<TParam>>() { } 

When the generic type (MyType in your case) is known, can't you just do

public MyType<TParam> Get<TParam>() { 
  return (MyType<TParam>)_items.FirstOrDefault(i => i is MyType<TParam>);
}

Or am I missing something?

Maxem
  • 2,634
  • 1
  • 20
  • 14
  • Maxem, it would be alright if I was implementing ICollection. But I'm rather implementing a generic collection, hence don't wanna get coupled to specific type instantiations. However, of course, I can create an extension-method for MyCollection with the implementation you provided. But it is a bit frustrating because it eliminates a generic approach. – Alec Oct 07 '11 at 09:59
  • Besides, the details of implementation of my collection can (probably) give me a result faster than using FirstOrDefault(), e.g. when I'm using a Dictionary internally. – Alec Oct 07 '11 at 10:05