D'autres ont souligné que cela ne déroge pas, mais cela laisse toujours votre question initiale: pourquoi êtes-vous capable de le faire? (Mais la question est vraiment "pourquoi pouvez-vous masquer les méthodes statiques".)
Il s'agit d'une caractéristique inévitable de la prise en charge du versionnement indépendant du composant qui contient des classes de base et des composants qui utilisent ces classes de base. Par exemple, imaginons que le composant CompB contient la classe de base et qu'un autre composant CompD contienne une classe dérivée. Dans la version 1 de CompB, il n'y aurait peut-être pas eu de propriété appelée LogName. L'auteur de CompD décide d'ajouter une propriété statique appelée LogName. La chose essentielle à comprendre à ce stade est que l'auteur de v1 de CompD n'avait pas l'intention de remplacer ou de cacher une caractéristique de la classe de base - il n'y avait aucun membre appelé LogName dans la classe de base quand ils ont écrit ce code.
Imaginez maintenant qu'une nouvelle version de la bibliothèque CompB soit publiée. Dans cette nouvelle version, l'auteur a ajouté une propriété LogName. Qu'est-ce qui est censé se passer dans CompD? Les options semblent être:
- Compd ne fonctionne plus parce que le LogName il introduit des affrontements avec le LogName ajouté à CompB
- D'une certaine façon faire LogName du Compd remplacer la base CompB LogName. Traitez les deux membres du LogName comme étant des membres complètement différents qui ont le même nom. (En réalité, ils ne s'appellent pas - ils s'appellent BaseLogger.LogName et SpecificLogger.LogName, mais comme en C# nous n'avons pas toujours besoin de qualifier le nom du membre avec la classe, on dirait qu'ils ont le même nom.)
.NET choisit de le faire 3. (et il le fait avec les deux et non statique Si vous voulez statics comportement 2 -. remplacement - avec non-statique, la base doit être virtual
et la classe dérivée doit marquer la méthode comme override
pour indiquer qu'ils ont volontairement surchargé une méthode dans la classe de base C# ne fera jamais remplacer la méthode d'une classe dérivée par une méthode dérivée à moins que la classe dérivée ait explicitement déclaré que c'est ce qu'ils voulu.) Ceci est susceptible d'être sûr parce que les deux membres sont non ed - le LogName de base n'existait même pas au point où le dérivé a été introduit. Et c'est préférable de simplement casser parce que la dernière version de la classe de base a introduit un nouveau membre.
Sans cette fonctionnalité, il serait impossible pour les nouvelles versions de .NET Framework d'ajouter de nouveaux membres aux classes de base existantes sans que cela ne constitue une rupture.
Vous dites que le comportement n'est pas ce que vous attendez. En fait, c'est exactement ce à quoi je m'attendais, et ce que vous voudriez probablement en pratique. Le BaseLogger n'a aucune idée que le SpecificLogger a introduit sa propre propriété LogName. (Il n'y a aucun mécanisme par lequel il pourrait parce que vous ne pouvez pas substituer des méthodes statiques.) Et quand l'auteur de SpecificLogger a écrit cette propriété LogName, rappelez-vous qu'ils écrivaient contre v1 de BaseLogger qui n'avait pas de LogName, donc ils n'avaient pas l'intention de remplacer la méthode de base non plus. Puisque aucune classe ne veut le remplacement, clairement le remplacement serait la mauvaise chose.
Le seul scénario dans lequel vous devriez vous retrouver dans cette situation est que les deux classes sont dans des composants différents. (Évidemment, vous pouvez concevoir un scénario quand ils sont dans le même composant, mais pourquoi le feriez-vous un jour? Si vous possédez les deux morceaux de code et les libérez dans un seul composant, il serait fou de le faire.) Et BaseLogger devrait donc avoir sa propre propriété LogName, ce qui est exactement ce qui se passe. Vous avez peut-être écrit:
SpecificLogger.Log("test");
mais le compilateur C# voit que SpecificLogger ne fournit pas une méthode Log, il transforme cela en:
BaseLogger.Log("test");
parce que c'est où la méthode Log est définie.
Chaque fois que vous définissez une méthode dans une classe dérivée qui ne tente pas de remplacer une méthode existante, le compilateur C# l'indique dans les métadonnées. (Il y a un paramètre "newslot" dans les métadonnées de la méthode qui indique que cette méthode est nouvelle, sans rapport avec quoi que ce soit dans la classe de base.)
Mais cela vous pose un problème si vous voulez recompiler CompD. Supposons que vous ayez un rapport de bogue dû à un bit de code totalement différent et que vous ayez besoin de lancer une nouvelle version de CompD. Vous le compilez contre la nouvelle version de CompB. Si le code que vous avez écrit n'était pas autorisé, vous ne seriez pas en mesure de - l'ancien code déjà compilé fonctionnerait, mais vous ne seriez pas capable de compiler de nouvelles versions de ce code, ce qui serait un peu fou . Et ainsi, pour soutenir ce scénario (franchement quelque peu obscur), ils vous permettent de le faire. Ils génèrent un avertissement pour vous informer que vous avez un conflit de nom ici. Vous devez fournir le mot-clé new
pour vous en débarrasser. Ceci est un scénario obscur, mais si vous voulez prendre en charge l'héritage à travers les limites des composants, vous en avez besoin, sinon l'ajout de nouveaux membres publics ou protégés sur une classe de base serait invariablement un changement de rupture. C'est pourquoi c'est ici. Mais c'est une mauvaise habitude de s'en remettre, d'où le fait que vous recevez un avertissement du compilateur. L'utilisation du mot-clé new
pour se débarrasser de l'avertissement ne devrait jamais être qu'un palliatif. La ligne de fond est la suivante: cette fonctionnalité existe pour une raison seulement, et c'est pour vous sortir d'un trou dans les situations où une nouvelle version d'une classe de base a ajouté un membre qui n'existait pas auparavant, et qui des conflits avec un membre qui est déjà sur votre classe dérivée. Si ce n'est pas le cas, n'utilisez pas cette fonctionnalité.
(je pense qu'ils devraient effectivement émettre une erreur plutôt que d'un avertissement lorsque vous excluez nouveau, pour le rendre plus clair.)
Comme d'autres l'ont dit, cela ne remplace pas - et il fait * exactement * comme je l'attendrais. S'il vous plaît, ne supposez pas que tout le monde pense de la même manière que vous. –