En C #, quelle est la différence entre public, privé, protégé et sans modificateur d'accès?

728

Toutes mes années de collège , j'ai utilisé public, et aimeraient connaître la différence entre public, privateet protected?

De plus, qu'est-ce qui staticfait plutôt que de ne rien avoir?

MrM
la source

Réponses:

1008

Modificateurs d'accès

De docs.microsoft.com :

public

Le type ou le membre est accessible par tout autre code du même assembly ou par un autre assembly qui le référence.

private

Le type ou le membre n'est accessible que par du code dans la même classe ou structure.

protected

Le type ou le membre n'est accessible que par du code dans la même classe ou structure, ou dans une classe dérivée.

private protected (ajouté en C # 7.2)

Le type ou le membre n'est accessible que par du code dans la même classe ou structure, ou dans une classe dérivée du même assembly, mais pas d'un autre assembly.

internal

Le type ou le membre est accessible par n'importe quel code du même assembly, mais pas à partir d'un autre assembly.

protected internal

Le type ou le membre est accessible par n'importe quel code du même assembly ou par n'importe quelle classe dérivée d'un autre assembly.

Si aucun modificateur d'accès n'est défini, un modificateur d'accès par défaut est utilisé. Il existe donc toujours une forme de modificateur d'accès même s'il n'est pas défini.

static modificateur

Le modificateur statique d'une classe signifie que la classe ne peut pas être instanciée et que tous ses membres sont statiques. Un membre statique a une version, quel que soit le nombre d'instances de son type englobant créées.

Une classe statique est fondamentalement la même chose qu'une classe non statique, mais il y a une différence: une classe statique ne peut pas être instanciée extérieurement. En d'autres termes, vous ne pouvez pas utiliser le nouveau mot clé pour créer une variable de type classe. Puisqu'il n'y a pas de variable d'instance, vous accédez aux membres d'une classe statique en utilisant le nom de classe lui-même.

Cependant, il existe un constructeur statique . Toute classe peut en avoir une, y compris les classes statiques. Ils ne peuvent pas être appelés directement et ne peuvent pas avoir de paramètres (autres que tous les paramètres de type sur la classe elle-même). Un constructeur statique est appelé automatiquement pour initialiser la classe avant la création de la première instance ou le référencement de tout membre statique. Ressemble à ça:

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }

    public static string Bar { get; set; }
}

Les classes statiques sont souvent utilisées comme services, vous pouvez les utiliser comme ceci:

MyStaticClass.ServiceMethod(...);
mbillard
la source
17
Et vous pouvez avoir des méthodes statiques dans des classes non statiques, non?
John Bubriski
14
Oui, ils se comporteraient de la même manière que dans mon exemple.
mbillard
7
Que signifie le terme «assemblage» dans ce contexte?
Jonathan Gleason
1
@gotoVoid Tout ce que vous avez recherché sur Google est incorrect. Selon MSDN , interne protégé signifie que «le type ou le membre est accessible par n'importe quel code de l'assembly dans lequel il est déclaré, ou à partir d'une classe dérivée dans un autre assembly».
Kevin
2
Quelle est la différence entre Protected et Private Protected? Pour moi, ça sonne les deux sont les mêmes ..
goofyui
161

Un aperçu graphique (résumé en bref)

Visibilité

Comme les classes statiques sont scellées, elles ne peuvent pas être héritées (sauf d'Object), donc le mot-clé protected n'est pas valide sur les classes statiques.



Pour les valeurs par défaut si vous ne mettez aucun modificateur d'accès devant, voyez ici:
Visibilité par défaut pour les classes et membres C # (champs, méthodes, etc.)?

Non imbriqué

enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

Imbriqué:

nested enum      public
nested interface public
nested class     private
nested struct    private

En outre, il existe un mot-clé scellé, qui rend une classe non héritable.
De plus, dans VB.NET, les mots-clés sont parfois différents, alors voici un cheat-sheet:

VB vs CS équivalents

Stefan Steiger
la source
1
@ ᴀʀᴜn BᴇrtiL: Êtes-vous sûr? Une classe dérivée dans un assemblage différent?
Stefan Steiger
classe dérivée dans le même assemblage que nous pouvons, différente nous ne pouvons pas. Je pensais que vous vouliez dire comme dans le même assemblage ...
Arun Bertil
1
@ ᴀʀᴜn BᴇrtiL: Hmm, à droite, cela devrait en fait être hachuré.
Stefan Steiger
1
Je pense qu'il y a une erreur dans le diagramme. Si internal est utilisé pour une classe, la classe peut être dérivée par une autre classe du même assembly. De plus, si le modificateur interne est utilisé sur une propriété, cette propriété est également accessible dans la classe dérivée du même assembly. Le diagramme est peut-être correct car il y a un "oui" sous "contenant contenant", mais il peut être mal compris car il y a un "non" sous "classes dérivées".
AH.
160

Public - Si vous pouvez voir la classe, alors vous pouvez voir la méthode

Privé - Si vous faites partie de la classe, vous pouvez voir la méthode, sinon non.

Protégé - Identique à Privé, et tous les descendants peuvent également voir la méthode.

Statique (classe) - Vous vous souvenez de la distinction entre "Classe" et "Objet"? Oubliez tout ça. Ils sont les mêmes avec "statique" ... la classe est l'instance unique d'elle-même.

Statique (méthode) - Chaque fois que vous utilisez cette méthode, elle aura un cadre de référence indépendant de l'instance réelle de la classe dont elle fait partie.

JosephStyons
la source
1
Ne pouvez-vous pas avoir des méthodes statiques dans une classe non statique?
John Bubriski
1
Oui, mais je parlais d'une classe statique. J'ai ajouté une entrée distincte pour décrire les méthodes statiques. Merci pour la capture.
JosephStyons
2
'Object' n'est peut-être pas un bon terme ici quand on parle de C #, car le type de base pour toutes les classes est System.Object . «Instance» serait un meilleur mot ou «objet» («O» en minuscules).
lesderid
@lesderid 'object' est un alias de 'System.Object', son utilisation peut aussi prêter à confusion. 'instance' serait mieux, je suppose :)
dpp
les mêmes règles s'appliquent aux structures.
gsharp
35

Republier les superbes diagrammes de cette réponse .

Voici tous les modificateurs d'accès dans les diagrammes de Venn, du plus limitant au plus promiscueux:

private:
entrez la description de l'image ici

private protected: - ajouté en C # 7.2
entrez la description de l'image ici

internal:
entrez la description de l'image ici

protected:
entrez la description de l'image ici

protected internal:
entrez la description de l'image ici

public:
entrez la description de l'image ici

Paul
la source
24

entrez la description de l'image ici

using System;

namespace ClassLibrary1
{
    public class SameAssemblyBaseClass
    {
        public string publicVariable = "public";
        protected string protectedVariable = "protected";
        protected internal string protected_InternalVariable = "protected internal";
        internal string internalVariable = "internal";
        private string privateVariable = "private";
        public void test()
        {
            // OK
            Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(publicVariable);

            // OK
            Console.WriteLine(protectedVariable);

            // OK
            Console.WriteLine(internalVariable);

            // OK
            Console.WriteLine(protected_InternalVariable);
        }
    }

    public class SameAssemblyDerivedClass : SameAssemblyBaseClass
    {
        public void test()
        {
            SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }

    public class SameAssemblyDifferentClass
    {
        public SameAssemblyDifferentClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // NOT OK
            // Console.WriteLine(privateVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            //Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }
}

 using System;
        using ClassLibrary1;
        namespace ConsoleApplication4

{
    class DifferentAssemblyClass
    {
        public DifferentAssemblyClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            // Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protectedVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protected_InternalVariable);
        }
    }

    class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
    {
        static void Main(string[] args)
        {
            DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            //Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);

            SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
            dd.test();
        }
    }
}
Narottam Goyal
la source
1
Je ne vois pas ce que cette réponse ajoute par rapport aux nombreuses autres réponses des cinq dernières années.
John Saunders,
4
Ceci est juste une explication simple. Comme les autres réponses sont un peu confuses et à moitié répondues :)
Narottam Goyal
4
@John Saunders: Il différencie en séparant la visibilité d'une classe dérivée entre cette classe étant dans la même et cette classe étant dans un assemblage différent. De plus, il explique comment il a obtenu ces informations en montrant son exemple de code. Cela s'ajoute donc aux autres réponses. Son nécromancement a probablement été déclenché par mon commentaire dans ma réponse.
Stefan Steiger
2
"Classe dérivée dans un assemblage différent" - cela ajoute de la valeur au graphique déjà donné dans une autre réponse. La différence est utile en particulier en cas de "protection interne"
Nirman
Je trouve que ce tableau est le plus facile à comprendre pour moi. Pour garder ce courant (avec C # 7.2), pour ajouter Private Protected, ce serait: même classe = Yes, même assemblage, classe dérivée = Yes, même assemblage, toute classe = NO, assemblage différent, classe dérivée = NO, assemblage différent, toute classe = NO. Une autre suggestion serait également de ne pas changer l'ordre des mots protected internal, car cela rompt le pneumonique de la réponse de @ user1810087
Intrastellar Explorer
22

Concernant la question du néant

  • Les types d'espace de noms sont internes par défaut
  • Tout membre de type, y compris les types imbriqués, est privé par défaut
leppie
la source
15

Encore une autre approche visuelle du modificateur d'accès actuel (C # 7.2). Espérons que le schéma aide à s'en souvenir plus facilement
(cliquez sur l'image pour une vue interactive.)

modificateurs d'accès interactif svg

Extérieur intérieur

Si vous avez du mal à vous souvenir des modificateurs d'accès à deux mots, souvenez - vous de l' extérieur à l'intérieur .

  • privé protégé : extérieur privé (même assemblage) protégé intérieur (même assemblage)
  • intérieur protégé : extérieur protégé (même assemblage) intérieur intérieur (même assemblage)
user1810087
la source
11

Hmm.

Voir ici: Modificateurs d'accès .

En un mot:

Public donne à la méthode ou au type une visibilité complète à partir d'autres types / classes.

Privé autorise uniquement le type contenant la méthode / variable privée à accéder à la méthode / variable privée (notez que les classes imbriquées ont également accès aux méthodes / variables privées des classes contenant).

Protégé est similaire à privé, sauf que les classes dérivées peuvent également accéder aux méthodes protégées.

"Nothing" est l'équivalent de VB.NET pour null. Bien que si vous faites référence à "rien" qui signifie "aucun modificateur d'accès", cela dépend, bien qu'une règle empirique très approximative (certainement en C #) soit que si vous ne spécifiez pas explicitement un modificateur d'accès, la méthode / variable déclaration est généralement aussi restreinte que possible. c'est à dire

public class MyClass
{
    string s = "";
}

est effectivement le même que:

public class MyClass
{
    private string s = "";
}

L'article MSDN lié offrira une description complète lorsqu'il n'y a aucun modificateur d'accès explicitement spécifié.

CraigTP
la source
8

public - peut être accessible par n'importe qui n'importe où.
privé - accessible uniquement depuis avec dans la classe dont il fait partie.
protégé - accessible uniquement à partir de avec dans la classe ou de tout objet qui hérite de la classe.

Rien n'est nul mais en VB.
Statique signifie que vous avez une instance de cet objet, méthode pour chaque instance de cette classe.

Tony
la source
4

mmm ...

Statique signifie que vous pouvez accéder à cette fonction sans avoir d'instance de la classe.

Vous pouvez accéder directement à partir de la définition de classe.

gbianchi
la source
4

Un état Privé indique que les variables ne sont accessibles que par des objets de la même classe. Le statut protégé étend cet accès pour inclure également les descendants de la classe.

"du tableau ci-dessus, nous pouvons voir la déférence entre privé et protégé ... je pense que les deux sont les mêmes .... alors quel est le besoin de ces deux commandes distinctes"

Vérifiez le lien MSDN pour plus d'informations

Grant Hood
la source
3

Ces modificateurs d'accès spécifient où vos membres sont visibles. Vous devriez probablement lire ceci. Prenez le lien donné par IainMH comme point de départ.

Les membres statiques sont un par classe et non un par instance.

jpfollenius
la source
3

Surveillez attentivement l'accessibilité de vos cours. Les classes et méthodes publiques et protégées sont par défaut accessibles à tous.

De plus, Microsoft n'est pas très explicite en montrant les modificateurs d'accès (mots-clés publics, protégés, etc.) lorsque de nouvelles classes dans Visual Studio sont créées. Alors, faites bien attention et pensez à votre accessibilité de votre classe car c'est la porte de vos implémentations internes.

Patrick Peters
la source
2

Je pense que cela est lié à une bonne conception de la POO. Si vous êtes développeur d'une bibliothèque, vous souhaitez masquer le fonctionnement interne de votre bibliothèque. De cette façon, vous pouvez modifier le fonctionnement interne de votre bibliothèque ultérieurement. Vous mettez donc vos membres et vos méthodes d'assistance en privé, et seules les méthodes d'interface sont publiques. Les méthodes qui doivent être écrasées doivent être protégées.

Darius Kucinskas
la source
1

C # a au total 6 modificateurs d'accès:

private : le membre déclaré avec cette accessibilité peut être visible dans le type conteneur, il n'est pas visible pour les types dérivés, les autres types du même assembly ou les types en dehors de l'assembly conteneur. c'est-à-dire que l'accès est limité au type conteneur uniquement.

protected : le membre déclaré avec cette accessibilité peut être visible dans les types dérivés du type conteneur dans l'assembly conteneur et les types dérivés du type conteneur en dehors de l'assembly conteneur. c'est-à-dire que l'accès est limité aux types dérivés du type conteneur.

internal : le membre déclaré avec cette accessibilité peut être visible dans l'assembly contenant ce membre, il n'est visible par aucun assembly en dehors de l'assembly conteneur. c'est-à-dire que l'accès est limité au contenu de l'assemblage uniquement.

Interne protégé : le membre déclaré avec cette accessibilité peut être visible dans les types dérivés du type conteneur à l'intérieur ou à l'extérieur de l'assembly conteneur, il est également visible pour tous les types au sein de l'assembly conteneur. c'est-à-dire que l'accès est limité au confinement des assemblys ou des types dérivés.

Publique : le membre déclaré avec cette accessibilité peut être visible dans l'assembly contenant ce membre, ou dans tout autre assembly faisant référence à l'assembly contenant. c'est-à-dire que l'accès n'est pas limité.

C # 7.2 ajoute un nouveau niveau d'accessibilité:

private protected : le membre déclaré avec cette accessibilité peut être visible dans les types dérivés de ce type conteneur dans l'assembly conteneur. Il n'est visible par aucun type non dérivé du type conteneur ou en dehors de l'assemblage conteneur. c'est-à-dire que l'accès est limité aux types dérivés au sein de l'assemblage conteneur.

Source comprenant un exemple de code du nouveau modificateur d'accès protégé privé

Baccata
la source
0

Toutes les descriptions des modificateurs d'accès pour C #

entrez la description de l'image ici

snr
la source