web-dev-qa-db-fra.com

Quel est le cas d'utilisation du modificateur (C # 7.2) "privé protégé"?

C # 7.2 introduit le modificateur privé protégé .

J'ai toujours protégé l'accès aux champs avec des propriétés, permettant l'accès via les méthodes Get/Set car je ne veux généralement pas que l'état interne de mon objet soit modifié par autre chose que ma propre classe.

J'essaie de comprendre pourquoi l'équipe du langage C # a ajouté cette fonctionnalité. Après une recherche approfondie sur google, et après avoir lu et regardé les médias 'quoi de neuf' (j'ai regardé les communiqué de presse , détails et vidéo de Mads Torgerson ), je ne suis toujours pas plus sage.

Pour moi, cela semble permettre à un développeur de briser le principe de substitution de Liskov, mais cela peut être dû au fait que je ne comprends pas pourquoi cette fonctionnalité existe maintenant.

Je comprends comment il peut être utilisé, mais pas pourquoi - s'il vous plaît quelqu'un peut-il fournir un exemple d'utilisation réel plutôt que celui artificiel dans les documents MSDN?

62
Jay

Avant C # 7.2, nous avions protected internal modificateur. Cela signifie vraiment protégé OR interne, c'est-à-dire que le membre A est accessible aux classes enfants et également à toute classe de l'assembly actuel, même si cette classe n'est pas enfant de la classe A (donc la restriction implicite de "protected" est assouplie).

private protected signifie vraiment protégé ET interne. C'est-à-dire que le membre n'est accessible qu'aux classes enfants qui se trouvent dans le même Assembly, mais pas aux classes enfants qui sont en dehors de Assembly (donc la restriction implicite de "protected" est restreinte - devient encore plus restrictive). Cela est utile si vous créez une hiérarchie de classes dans votre assembly et que vous ne souhaitez pas que les classes enfants d'autres assemblys accèdent à certaines parties de cette hiérarchie.

Nous pouvons prendre l'exemple que Jon Skeet fourni dans les commentaires . Supposons que vous ayez de la classe

public class MyClass {

}

Et vous voulez pouvoir en hériter uniquement dans l'assembly actuel, mais vous ne voulez pas autoriser l'instanciation de cette classe directement, sauf à partir de cette hiérarchie de classes.

L'héritage uniquement au sein de l'assembly actuel peut être réalisé avec le constructeur interne

public class MyClass {
    internal MyClass() {
    }
}

La prévention de l'instanciation directe, à l'exception de la hiérarchie de classe actuelle, peut être obtenue avec le constructeur protégé:

public class MyClass {
    protected MyClass() {
    }
}

Et pour obtenir les deux - vous avez besoin de private protected constructeur:

public class MyClass {
    private protected MyClass() {
    }
}
59
Evk

Supposons que vous ayez une classe interne appelée SomeHelper que vous souhaitez utiliser dans le cadre de l'implémentation d'une classe de base abstraite publique:

public abstract class Test
{
    // Won't compile because SomeHelper is internal.
    protected SomeHelper CreateHelper()
    {
        return new SomeHelper();
    }

    public int Func(int x)
    {
        var helper = CreateHelper();
        return helper.DoSomething(x);
    }
}

internal class SomeHelper
{
    public virtual int DoSomething(int x)
    {
        return -x;
    }
}

Cela ne se compilera pas car vous ne pouvez pas avoir de méthode protégée renvoyant un type interne. Votre seul recours est de ne pas utiliser SomeHelper de cette façon, ou de rendre SomeHelper public.

(Vous pouvez faire de SomeHelper une classe interne protégée de Test, mais cela ne fonctionnera pas si SomeHelper est destiné à être utilisé par d'autres classes qui ne dérivent pas de la base classe.)

Avec l'introduction de la fonction private protected, Vous pouvez déclarer CreateHelper() comme ceci:

private protected SomeHelper CreateHelper()
{
    return new SomeHelper();
}

Maintenant, il va compiler, et vous n'avez pas à exposer vos éléments internes.

8
Matthew Watson

Pour les modificateurs d'accès à deux mots j'ai ce concept - le premier accesseur est lié à un autre assembly, le second à l'assembly dans lequel il a été défini.

interne protégé

  • protégé dans un autre Assembly: accessible uniquement dans les classes enfants.

  • interne dans l'assemblage actuel: accessible à tous dans l'assemblage actuel.

privé protégé

  • privé dans un autre assembly: n'est pas accessible.
  • protégé dans l'assembly actuel: accessible uniquement dans les classes enfants.
8
Suren Srapyan