Konamiman
Konamiman

Reputation: 50273

How to specify a generic type as a restriction in a generic method

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.

Upvotes: 2

Views: 1301

Answers (5)

LukeH
LukeH

Reputation: 269368

interface IMyGenericBase { /* ... */ }

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

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

T GetInstanceOf<T>() where T : IMyGenericBase { /* ... */ }

Upvotes: 4

Eric Lippert
Eric Lippert

Reputation: 660024

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?

Upvotes: 2

Reed Copsey
Reed Copsey

Reputation: 564403

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".

Upvotes: 1

AaronSieb
AaronSieb

Reputation: 8266

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_topic12

Upvotes: 6

Jesse Taber
Jesse Taber

Reputation: 2386

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.

Upvotes: 1

Related Questions