tags:

views:

177

answers:

5

I have a generic class like this:

class MyGenericClass<T> { }

On the other hand I have an aggregator class that I use to obtain singleton instances of MyGenericClass and of derived classes, where each instance is identified by the concrete class type and by the parameter type. That is, MyGenericClass<int> is different from MyGenericClass<string> and from MyDerivedGenericClass<int>; there is one single instance for each of them.

The main member of the aggregator is the GetInstanceOf method, which will return the singleton instance of the specified type. The problem is that I want to specify the type as a generic parameter, but I can't find a way to create a restriction of type "the parameter must be of type MyGenericClass (or derived) with any parameter type". In short, I want something like this:

T GetInstanceOf<T>() where T : MyGenericClass<> //This does not compile

So, what can I do? Is there any way to specify such a restriction?

EDIT: The GetInstanceOf<T> method indeed returns T, not void.

+5  A: 

You probably want to create an interface, and have your generic class implement that. MyGenericClass<int> and MyGenericClass<string> are considered to be completely different classes by the .NET compiler.

This would allow you to do something like this:

void GetInstanceOf<T>() where T : IMyGenericClass

You could also use a shared base class:

void GetInstanceOf<T>() where T : MyGenericClassBase

Finally, you might try to add a second type parameter to your method:

void GetInstanceOf<T, U>() where T: MyGenericClassBase<U>

(I'm not sure about that last one... I don't have a compiler handy to check it)

See: http://msdn.microsoft.com/en-us/library/aa479859.aspx#fundamentals%5Ftopic12

AaronSieb
I finally chose to have the generic class to implement an interface and it worked fine. Thanks everybody!
Konamiman
+4  A: 
interface IMyGenericBase { /* ... */ }

class MyGenericClass<T> : IMyGenericBase { /* ... */ }

class MyDerivedGenericClass<T> : MyGenericClass<T> { /* ... */ }

T GetInstanceOf<T>() where T : IMyGenericBase { /* ... */ }
LukeH
+1  A: 

If it were me I would likely create an interface, have 'MyGenericClass' implement that interface, and then use the interface in the 'where' of your method signature.

Jesse Taber
+1  A: 

I agree with most posts here - providing an interface is typically the best approach.

However, if MyGenericClass<T> happens to be a class defined outside of your control, the other option is to do:

 void GetInstanceOf<T, U>() where T : MyGenericClass<U>

Unfortunately, this requires your caller to provide the generic type of MyGenericClass as well, but it will compile and run correctly if you cannot change "MyGenericClass".

Reed Copsey
+2  A: 

I think you're making this much more complicated than it needs to be. Take a step back and solve the real problem, rather than trying to solve some completely unnecessary issue involving constraints. This seems very straightforward:

MyGenericClass<T> GetInstanceOfMyGenericClass<T>() 
{ 
    return MyGenericClass<T>.GetSingleton(); 
}

You want a MyGenericClass<int>, you say GetInstanceOfMyGenericClass<int>(), done. Why mess around with constraints at all if you don't need to?

Eric Lippert