43 votes

Pourquoi les méthodes virtuelles privées sont-elles illégales dans le CMD?

Venant d'un C++ fond, c'est venu comme une surprise pour moi. En C++ c'est une bonne pratique pour faire des fonctions virtuelles privé. À partir de http://www.gotw.ca/publications/mill18.htm: "la ligne Directrice n ° 2: Préférez faire des fonctions virtuelles privées".

J'ai aussi citer Eric Lippert du blog, de Chevaliers-les démons-protégé-et-interne:

Privé virtuel méthodes sont illégales en C#, ce qui ne m'irrite pas de fin. J' serait tout à fait utiliser cette fonctionnalité si nous l'avions.

Je comprends qu'en C#, vous ne seriez pas en mesure de remplacer un privé virtuel méthode dans un dérivé (mais pas imbriquée) de la classe. Pourquoi est-ce le cas? En C++, le spécificateur d'accès n'a rien à voir avec le fait que vous pouvez remplacer une fonction ou pas.

41voto

Eric Lippert Points 300275

Je remarque qu'il y a deux questions ici. Dans le futur, vous pourriez envisager d'afficher deux questions au lieu de la combinaison de deux questions en une seule. Lorsque vous combinez des questions de ce genre souvent ce qui se passe n'est que la première, on obtient une réponse.

La première question est "pourquoi êtes-privé virtuel des méthodes illégales en C#?"

Voici les arguments contre le "privé virtuel méthodes" fonctionnalité:

  1. privé virtuel n'est utile que lorsque vous avez un imbriquée de la classe dérivée. C'est un bon modèle, mais bien moins courante que la non-dérivées imbriquées situation de classe.

  2. Si vous le désir de restreindre la capacité de remplacer la méthode de la non-imbriquées les classes dérivées, vous pouvez le faire en limitant la capacité des non-classes imbriquées à dériver de la classe de base; faire toute la classe de base des constructeurs privés. Par conséquent privé virtuel n'est pas nécessaire de prévenir primordial; virtuelles protégées est suffisante, parce que les seules classes dérivées seront imbriquées.

  3. Si vous désirez restreindre la capacité d' appeler une méthode dans un non-dérivées imbriquées classe puis vous pouvez faire de la méthode virtuelle interne, puis dites à vos collègues de ne pas utiliser cette méthode. Il est irritant pour avoir ce soit pas appliquée par le compilateur, mais le compilateur ne pas l'application de toute autre contrainte sémantique sur comment une méthode est censé être utilisé, d'obtenir le droit de la sémantique, c'est votre affaire, pas le compilateur, et que vous avez à faire valoir avec le code approprié examens. Par conséquent privé virtuel n'est pas nécessaire pour empêcher l'appelant; virtuel interne en plus des revues de code est suffisant.

  4. Il est possible de mettre en œuvre ce modèle déjà avec des pièces existantes:

    abstract class C
    {
        private int CF() { whatever; }
        private Func<int> f;
        public C() { f = CF; } 
        private int F() { return f(); }
        private class D : C
        {
            private int DF() { whatever; }
            public D() { f = DF; }
        }
    

    Maintenant, j'ai une méthode F qui est effectivement virtuel, mais ne peut être "remplacée" par des dérivés classes imbriquées.

Depuis, dans tous les cas soit protégé, interne ou interne protégée fait l'astuce, privé virtuel est inutile. Elle n'est presque jamais la bonne chose à faire, puisque vous avez déjà déterminé à l'aide de la dérivée imbriquée de la classe de modèle. Donc, la langue la rend illégale.

Les arguments sont les suivants:

Il ya eu des moments dans le code réel, quand j'ai envie d'une méthode virtuelle privé en détail de l'implémentation d'une classe que je veux être étendue à la fois par des non-nested classes internes et imbriquée à l'intérieur des classes. Avoir à appliquer l'invariant que la méthode interne de ne pas être appelé par mes collègues de travail est délicate; je voudrais qu'être appliquées par le compilateur sans avoir à me sauter à travers un fou cerceaux comme faire un champ de type délégué, etc.

Aussi, il n'y a tout simplement la question de la cohérence et de l'orthogonalité. Il semble étrange que les deux choses qui se doit d'être indépendant, de l'accessibilité et de virtualness -- avoir un effet sur les uns les autres inutilement.

Les arguments contre sont assez fortes. Les arguments sont bien faibles. Par conséquent, aucune fonctionnalité. Je serais personnellement très envie, mais je comprends totalement pourquoi l'équipe de conception a jamais pris de moi sur elle. Ça ne vaut pas le coût, et je ne voudrais pas de ne pas expédier une meilleure fonctionnalité, car nous avons passé budget sur une fonctionnalité que les avantages ou presque.

La deuxième question est "Pourquoi en C# n'êtes-vous pas en mesure de remplacer un privé virtuel méthode dans un dérivé non-classe imbriquée?"

Il y a plusieurs raisons.

  1. Parce que vous ne pouvez remplacer ce que vous pouvez voir. Une méthode privée est un privé détail de l'implémentation d'une classe de base et ne doit pas être accessible.

  2. Car permettre à, qui a de graves conséquences sur la sécurité. Rappelez-vous, en C++, vous avez presque toujours compiler du code dans une application à la fois. Vous avez le code source de tout; tout ce qui est essentiellement "interne" du C++ point de vue la plupart du temps. En C#, ce n'est pas du tout le cas. Troisième partie les assemblées peuvent facilement obtenir au public les types de bibliothèques et de produire de nouvelles extensions pour les classes qui peuvent ensuite être utilisés de façon transparente en place d'instances de la classe de base. Depuis virtuel efficace des méthodes de modifier le comportement d'une classe, tout code qui dépend, pour des raisons de sécurité sur les invariants de cette classe doit être soigneusement conçu de sorte qu'ils ne dépendent pas des invariants garanti par la classe de base. La restriction de l'accessibilité des méthodes virtuelles permet de s'assurer que les invariants de ces méthodes sont maintenus.

  3. Car permettre à, qui fournit une autre forme de la fragile de la classe de base problème. C# a été soigneusement conçu pour être moins sensibles à la fragile de la classe de base problème que d'autres langages à objets. Si un inaccessible virtuel méthode peut être redéfinie dans une classe dérivée, puis privé de détail de l'implémentation de la classe de base devient une modification de rupture si altérée. Les fournisseurs de classes de base doit être libre de changer de détails internes sans se soucier de l'excès qu'ils ont cassé les classes dérivées qui en dépendent; idéalement, le public, documentée d'une interface de type doit être maintenu lorsque les détails de mise en œuvre du changement.

15voto

Darko Z Points 16570

Parce que les méthodes privées ne peuvent être accessibles à partir de la classe de les définir, d'où un privé virtuel méthode serait inutile. Ce que vous voulez est une méthode virtuelle protégée. Une méthode protégée peut être consulté par la classe de définition et de toutes les sous-classes.

EDIT:

En fournissant privé et protégé les mots clés de C# permet un contrôle plus précis de vos méthodes. Qui est privé des moyens complètement fermé et protégé signifie complètement fermé en dehors de sous-classes. Cela vous permet de disposer de méthodes pour que seul votre classe mère sait à ce sujet et les méthodes qui sous-classes peuvent connaître.

5voto

Dean Harding Points 40164

Je suppose que la raison en est que fait *presque* la même chose que et est un peu moins déroutant pour ceux qui ne connaissent pas l'idiome. ``

Alors que seules les classes intérieures pouvaient remplacer les méthodes, seules les classes de votre assemblée peuvent l'emporter sur les méthodes.

2voto

cHao Points 42294

Dans le CMD (et dans le CLI, autant que j'ai vu), "privé" a une signification assez claire et sans ambiguïté: "accessible seulement dans cette classe". Le concept de virtuels privés visse tout cela, sans parler de faire des espaces de noms un peu d'un champ de mines. Pourquoi devrais-je avoir à se soucier de ce que vous avez appelé une méthode que je ne peux même pas voir, et obtenir un avertissement compilateur pour se produire d'avoir choisi un nom que vous avez déjà accroché pour elle?

2voto

Igor Zevaka Points 32586

Parce que le C# n'a pas de mécanisme pour permettre au public/privé/protégé de l'héritage, qui est ce que l'on en fait après.

Même en C++, les membres privés ne sont pas accessibles par les classes dérivées, mais ils peuvent limiter la classe de base de la visibilité par la spécification de l'héritage de la visibilité:

class Derived : /*->>*/private/*<--*/ Base {
}

C# fournit tout un tas d'autres choses dans l'ordre pour vous de contrôler la visibilité de votre classe de membres. Entre protected et internal, vous devriez être en mesure d'obtenir la hiérarchie exactement comme vous le souhaitez.

À mon humble avis C# applique plus forte relation " EST-UN par classe de base unique de l'héritage, il est donc logique que si une voiture a un moteur, une BMW sous-classe ne devrait pas être capable de le cacher.

C++ supporte l'héritage multiple qui est moins strictes de la relation " EST-UN - c'est presque comme un A-UNE relation où l'on peut apporter dans plusieurs classes indépendantes. En raison de la capacité d'apporter plusieurs classes de base, vous voulez plus de contrôle sur la visibilité de tous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X