Question

Excusez-moi si cela est dupe, mais je ne pouvais pas sembler obtenir la bonne combinaison de mots-clés pour affiner votre recherche en différentes contraintes de type et génériques des questions là-bas (comme il y a beaucoup).

J'ai deux interfaces - appelons-les Ionline et IOffline .

Ils sont étroitement liés en ce qu'ils décrivent des contrats presque identiques, mais l'une des principales différences entre eux est le contexte dans lequel les mises en œuvre concrètes seront utilisées. Ce n'est pas exactement ma situation, mais il illustre bien le problème.

J'ai alors quelques méthodes là-bas qui ne fonctionnent contre les agents d'exécution concrètes de ces interfaces. Parfois, ces méthodes ne veulent que faire face à un type et non l'autre.

Assez simple:

public void DoStuff<T>(string foo) where T : IOnline {}

Le botteur met en œuvre le code des méthodes qui peuvent fonctionner sur le type non plus. Je pensais que ce serait correct, mais en lisant l'erreur de compilation, mes attentes que la contrainte serait interprétée comme « permettre à tout type T à utiliser génériquement ici si elles mettent en œuvre Ionline OU IOffline », est effectivement interprété comme « Autoriser tout type T à utiliser génériquement ici si elles mettent en œuvre les deux. »

public void DoStuff<T>(string foo) where T : IOnline, IOffline {}

Essayer de mettre en œuvre deux méthodes distinctes avec le même nom, mais des contraintes différentes échoue car il y a des problèmes d'ambiguïté évidente - ne pas surcharger car nous sommes des la liste des paramètres est le même (puisque le comportement souhaité est identique).

peut utiliser deux noms différents pour deux méthodes différentes, chacune avec la contrainte appropriée, mais qui semble kludgy et fait d'autres choses en aval comme une douleur dans le cul ... faisables, mais pas idéal.

Je me sens comme il doit y avoir quelque chose que je manque ici ... Je me sens parfaitement à l'aise dans la terre générique, mais c'est la première fois que je devais accomplir ce que je suis après et je sens que je suis à filer atm mes roues.

Était-ce utile?

La solution

Fournir de multiples contraintes que dans votre deuxième exemple est en effet additif. la page MSDN sur les contraintes génériques a un peu à ce sujet.

Pouvez-vous faire vos deux interfaces héritent d'une interface de base, et contraindre les méthodes du type de base?

Autres conseils

Ceci est peut-être pas une réponse à votre question, mais je reçois spontanément le sentiment que vous pouvez factoriser vos interfaces. De votre question:

  

Ils sont étroitement liés en ce qu'ils   décrire les contrats presque identiques,   mais l'une des principales différences entre   eux est le contexte dans lequel la   implémentations concrètes seront utilisées.

Mon point de vue des interfaces est que ils sont des contrats . Ils définissent la façon dont quelque chose doit regarder , pas exactement comment il se doit comportent ; qui est la tâche de la mise en œuvre. Maintenant, je n'ai pas d'informations sur votre application ou d'un domaine de problème, mais je voudrais essayer probablement de passer du temps sur l'identification des pièces identiques de ces interfaces et les déplacer dans une seule interface, et ne garder que les Différencies interfaces distinctes. De cette façon, vous pourriez peut-être naviguer passé ce genre de problèmes plus facilement.

Je pense que la manière standard dans .NET pour ce faire est d'avoir une interface qui contient à la fois vos fonctions Ionline et IOffline, puis quelques propriétés qui disent quelles fonctions sont effectivement mises en œuvre dans une classe spécifique. Vous voyez ce modèle dans divers endroits .NET avec des choses comme une méthode de recherche () qui pourrait ou non être mis en œuvre et une propriété CanSeek que vous pouvez tester.

Il est peut-être pas la plus propre conception OO, mais il fonctionne.

perd de la compilation du temps à vérifier, mais je ne vois aucune façon autour d'elle ... Vous ne devez choisir que vous utiliseriez plutôt, (je suppose votre préférence serait en ligne):

public void DoStuff<T>(string foo)
{
    Type type = typeof(T);
    if(type.GetInterfaces().Contains(typeof(IOnline)))
         doStuffOnline<T>(foo);
    else if(type.GetInterfaces().Contains(typeof(IOffline)))
         doStuffOffline<T>(foo);
    else
         throw new Exception("T must implement either IOnline or IOffline");
}

private void doStuffOnline<T>(string foo){ // can assume T : IOnline }
private void doStuffOffline<T>(string foo){ // can assume T : IOffline }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top