2009-10-15 6 views
2

J'ai une classe générique comme ceci:Comment spécifier un type générique comme une restriction dans une méthode générique

class MyGenericClass<T> { } 

D'autre part, j'ai une classe aggrégateur que j'utilise pour obtenir des instances singleton de MyGenericClass et des classes dérivées, où chaque instance est identifiée par le type de classe concret et par le type de paramètre. Autrement dit, MyGenericClass<int> est différent de MyGenericClass<string> et de MyDerivedGenericClass<int>; il y a une seule instance pour chacun d'eux.

Le membre principal de l'agrégateur est la méthode GetInstanceOf, qui renvoie l'instance singleton du type spécifié. Le problème est que je veux spécifier le type comme un paramètre générique, mais je ne peux pas trouver un moyen de créer une restriction de type "le paramètre doit être de type MyGenericClass (ou dérivé) avec tout type de paramètre". En bref, je veux quelque chose comme ceci:

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

Alors, que puis-je faire? Y a-t-il un moyen de spécifier une telle restriction? La méthode GetInstanceOf<T> renvoie effectivement T, non vide.

+0

Je suis confus: pourquoi votre méthode * a-t-elle été déclarée comme étant nulle, mais * décrite * comme renvoyant une valeur? –

+0

Vous avez raison, je l'ai mal écrit. C'est corrigé maintenant. Pardon. – Konamiman

Répondre

6

Vous souhaitez probablement créer une interface et la mettre en œuvre dans votre classe générique. MyGenericClass <int> et MyGenericClass < chaîne > sont considérés comme des classes complètement différentes par le compilateur .NET.

Cela vous permettra de faire quelque chose comme ceci:

void GetInstanceOf<T>() where T : IMyGenericClass 

Vous pouvez également utiliser une classe de base commune:

void GetInstanceOf<T>() where T : MyGenericClassBase 

Enfin, vous pouvez essayer d'ajouter un second paramètre de type à votre méthode:

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

(Je ne suis pas sûr de ce dernier ... Je n'ai pas de compilateur à portée de main o vérifier) ​​

Voir: http://msdn.microsoft.com/en-us/library/aa479859.aspx#fundamentals_topic12

+0

J'ai finalement choisi d'avoir la classe générique pour implémenter une interface et ça a bien fonctionné. Merci à tous! – Konamiman

4
interface IMyGenericBase { /* ... */ } 

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

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

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

Si c'était moi je créerais probablement une interface, ont « MyGenericClass » mettre en œuvre cette interface, puis utilisez l'interface dans le « où » de votre méthode Signature.

1

Je suis d'accord avec la plupart des messages ici - fournir une interface est généralement la meilleure approche.

Cependant, si MyGenericClass<T> arrive à une classe définie hors de votre contrôle, l'autre option est de faire:

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

Malheureusement, cela exige que votre correspondant pour fournir le type générique de MyGenericClass aussi, mais il compilera et fonctionnera correctement si vous ne pouvez pas changer "MyGenericClass".

2

Je pense que vous êtes en train de rendre cela plus compliqué que nécessaire.Prenez du recul et résolvez le vrai problème, plutôt que d'essayer de résoudre un problème complètement inutile impliquant des contraintes. Cela semble très simple:

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

Vous voulez un MyGenericClass<int>, vous dites GetInstanceOfMyGenericClass<int>(), fait. Pourquoi déranger avec des contraintes du tout si vous n'en avez pas besoin?

Questions connexes