2009-11-29 6 views
5

Est-il possible de contraindre une méthode générique à accepter uniquement des types spécifiques de structure?Génériques C#, Contraindre à des structures spécifiques

C'est OK je crois:

string Add<T>(object value, T expiration) where T : struct; 

mais ce n'est pas il apparaît:

string Add<T>(object value, T expiration) where T : Struct1, Struct2; 

Note: les struct Je souhaite contraindre à se DateTime ou TimeSpan et donc je pas de contrôle sur eux.

Merci

Répondre

7

Non, car une structure est scellée (vous ne pouvez pas créer une sous-classe d'un ValueType).

Au lieu de cela, envisager d'avoir votre struct implémenter une interface, puis utilisez que comme une contrainte, comme ceci:

string Add<T>(object value, T expiration) where T : struct, IMyInterface

+0

Je suis d'accord que cela devrait être réalisé avec des interfaces. C'est l'un des buts d'une interface! – Henri

+0

Merci pour votre réponse - s'il vous plaît pouvez-vous expliquer l'importance de ne pas être en mesure de sous-classer le type? Contraindre le paramètre à structs (types de valeur) semble possible et contradictoire à votre déclaration. Les structs que je souhaite contraindre sont DateTime ou TimeSpan, donc envelopper ceux-ci dans une interface semblerait être la seule solution (ou laisser un générique). – Ben

+2

Vous ne pouvez pas appliquer une nouvelle interface sur une structure que vous ne contrôlez pas ('DateTime',' TimeSpan' etc), donc non: vous ne pouvez pas le faire. –

-3

Je pense que les deux ne sont pas OK, une struct n'est pas une contrainte valide. Un type utilisé comme contrainte doit être interface, non scellé ou un paramètre de type

+1

http://msdn.microsoft.com/en-us/library/d5x73970.aspx indique que le premier est OK – Ben

+0

En effet, il existe d'autres contraintes au-delà des types: "new()" "struct" ou "class". –

5

Je me attends à une surcharge est votre meilleure option ici:

string Add(object value, MyStruct1 expiration) {...} 
string Add(object value, MyStruct2 expiration) {...} 

Ceci est d'autant plus approprié que vous ne pouvez pas sous-classer une structure, donc le seulement viable T dans votre exemple seraitMyStruct1 et MyStruct2 - peut également avoir des méthodes spécifiques, alors. Ré-limiter les génériques à plusieurs types cités; pas vraiment - et même s'il y en avait, le nom "Add" suggère que vous voulez utiliser le support de l'opérateur, qui aussi n'est pas en C# (3.0). Cependant, en C# 4.0, dynamic peut être une option ici - cela agit comme une forme optimisée de dactylographie; vous n'obtiendrez pas le support du compilateur (validation, etc), mais cela devrait fonctionner. Vous jetterait à l'intérieur dynamic la méthode:

string Add<T>(object value, T expiration) where T : struct { 
    dynamic valueDyn = value; 
    valueDyn += expiration; // or similar 
    // more code 
} 

Une autre option (.NET 3.5) est d'utiliser le Operator support dans MiscUtil, en utilisant Operator.Add ou Operator.AddAlternative.

7

Le but des génériques est de créer des méthodes et des types génériques, d'où le nom. Si vous n'avez que deux arguments de type possibles, alors écrivez simplement deux méthodes. N'oubliez pas que les génériques C# ne sont pas des modèles C++. Lorsque vous appelez une méthode sur un paramètre de type, disons, cet appel de méthode sera exactement la même méthode appelez pour chaque construction du paramètre de type. C'est générique. Ce n'est pas un modèle où le compilateur compile le code deux, trois, mille fois, un pour chaque argument de type, et élabore à nouveau pour chacun ce que l'appel de la méthode est.

Donc, même si vous pouvez restreindre votre argument de type à deux types, à quoi cela vous conviendrait-il? Tout ce que vous pouvez leur demander, ce sont les méthodes qu'ils ont en commun via leur classe de base, Object. Dans ce cas, vous avez une méthode générique qui fonctionne sur tous les objets, alors pourquoi le restreindre à deux types?

+0

Pourrait utiliser 'void Foo (T x) où T: I' au lieu de' void Foo (I x) 'aider à éviter la boxe de« x »quand' T' est un type par valeur? [Voici une question connexe] (http://stackoverflow.com/q/31457682/335858). – dasblinkenlight

Questions connexes