Il a été discuté précédemment sur Stack Overflow que nous devrions préférer les attributs aux interfaces de marquage (interfaces sans aucun membre). Article sur la conception d'interfaces sur MSDN affirme également cette recommandation :
Évitez d'utiliser des interfaces de marquage (interfaces sans membres).
Les attributs personnalisés permettent de marquer un type. Pour plus d'informations sur les attributs personnalisés, voir Écrire des attributs personnalisés. Les attributs personnalisés sont préférables lorsque vous pouvez différer la vérification de l'attribut jusqu'à l'exécution du code. Si votre scénario exige une vérification au moment de la compilation, vous ne pouvez pas vous conformer à cette ligne directrice.
Il y a même un Règle FxCop pour mettre en œuvre cette recommandation :
Éviter les interfaces vides
Les interfaces définissent des membres qui fournissent un comportement ou un contrat d'utilisation. La fonctionnalité décrite par l'interface peut être adoptée par n'importe quel type, quelle que soit sa position dans la hiérarchie de l'héritage. Un type implémente une interface en fournissant des implémentations pour les membres de l'interface. Une interface vide ne définit aucun membre et, en tant que telle, ne définit pas de contrat pouvant être mis en œuvre.
Si votre conception inclut des interfaces vides que les types sont censés implémenter, vous utilisez probablement une interface comme marqueur, ou comme moyen d'identifier un groupe de types. Si cette identification doit avoir lieu au moment de l'exécution, la bonne façon d'y parvenir est d'utiliser un attribut personnalisé. Utilisez la présence ou l'absence de l'attribut, ou les propriétés de l'attribut, pour identifier les types cibles. Si l'identification doit avoir lieu à la compilation, l'utilisation d'une interface vide est acceptable.
L'article ne mentionne qu'une seule raison pour laquelle vous pouvez ignorer l'avertissement : lorsque vous avez besoin d'une identification des types au moment de la compilation. (Ceci est cohérent avec l'article sur la conception des interfaces).
Il est possible d'exclure un avertissement de cette règle si l'interface est utilisée pour identifier un ensemble de types au moment de la compilation.
Voici la question proprement dite : Microsoft n'a pas respecté ses propres recommandations dans la conception de la Framework Class Library (au moins dans quelques cas) : Interface IRequiresSessionState y Interface IReadOnlySessionState . Ces interfaces sont utilisées par le cadre ASP.NET pour vérifier s'il doit activer l'état de session pour un gestionnaire spécifique ou non. De toute évidence, elles ne sont pas utilisées pour l'identification des types au moment de la compilation. Pourquoi n'ont-ils pas fait cela ? Je vois deux raisons possibles :
-
Micro-optimisation : Vérification de l'implémentation d'une interface par un objet (
obj is IReadOnlySessionState
) est plus rapide que l'utilisation de la réflexion pour vérifier la présence d'un attribut (type.IsDefined(typeof(SessionStateAttribute), true)
). La différence est négligeable la plupart du temps, mais elle peut avoir de l'importance pour un chemin de code critique en termes de performances dans le moteur d'exécution ASP.NET. Cependant, il existe des solutions de contournement, comme la mise en cache du résultat pour chaque type de gestionnaire. Ce qui est intéressant, c'est que les services Web ASMX (qui sont soumis à des caractéristiques de performance similaires) utilisent en fait la fonctionEnableSession
propriété de laWebMethod
attribut à cette fin. -
La mise en œuvre d'interfaces est potentiellement plus susceptible d'être prise en charge que la décoration de types avec des attributs par des langages .NET tiers. Puisque ASP.NET est conçu pour être agnostique en matière de langage, et que ASP.NET génère du code pour les types (éventuellement dans un langage tiers à l'aide de la fonction CodeDom ) qui mettent en œuvre lesdites interfaces sur la base de la
EnableSessionState
de l'attribut<%@ Page %>
directive il serait peut-être plus judicieux d'utiliser des interfaces plutôt que des attributs.
Quelles sont les raisons convaincantes d'utiliser des interfaces de marqueurs plutôt que des attributs ?
S'agit-il simplement d'une optimisation (prématurée ?) ou d'une petite erreur dans la conception du cadre ? (Pensent-ils que le reflet est un "grand monstre aux yeux rouges" ?) Réflexions ?
3 votes
Au risque de paraître trop sarcastique, qu'a fait Microsoft pour que vous vous attendiez à ce que l'on vous donne des conseils sur la façon d'utiliser l'Internet ? cohérence de leur part ? Ils ont fourni beaucoup d'outils et de logiciels utiles au fil des ans, mais la seule chose que je n'ai jamais vue de leur part, c'est un comportement cohérent ou le respect de leurs propres lignes directrices ou règles.
5 votes
@jalf : Je suis d'accord qu'ils sont connus pour ne pas adhérer à leurs propres directives, mais pour être juste, ils ont fait du bon travail dans .NET. Le .NET Framework fait preuve d'une grande cohérence et est généralement très bien conçu.
1 votes
en général très bien conçu, oui, et exceptionnellement cohérent, mais pas parfaitement. Il y a beaucoup de petites erreurs de conception stupides qui sont évidentes rétrospectivement. Mais comme l'indique la réponse de Mark, ces problèmes n'étaient probablement pas aussi évidents lors de la conception de la BCL - et les recommandations des lignes directrices ne l'étaient donc pas non plus.
4 votes
@jalf : parfois la conception précède la recommandation de la ligne directrice.