In C #, qual è la differenza tra pubblico, privato, protetto e senza modificatore di accesso?


728

Tutti i miei anni universitari ho utilizzato public, e vorrei sapere la differenza tra public, privatee protected?

Inoltre cosa fa staticinvece di non avere nulla?

Risposte:


1008

Modificatori di accesso

Da docs.microsoft.com :

public

È possibile accedere al tipo o al membro da qualsiasi altro codice nello stesso assembly o in un altro assembly a cui fa riferimento.

private

È possibile accedere al tipo o al membro solo tramite codice nella stessa classe o struttura.

protected

È possibile accedere al tipo o al membro solo tramite codice nella stessa classe o struttura, o in una classe derivata.

private protected (aggiunto in C # 7.2)

È possibile accedere al tipo o al membro solo tramite codice nella stessa classe o struttura, o in una classe derivata dallo stesso assembly, ma non da un altro assembly.

internal

È possibile accedere al tipo o al membro da qualsiasi codice nello stesso assembly, ma non da un altro assembly.

protected internal

È possibile accedere al tipo o al membro da qualsiasi codice nello stesso assembly o da qualsiasi classe derivata in un altro assembly.

Quando non è impostato alcun modificatore di accesso, viene utilizzato un modificatore di accesso predefinito. Quindi c'è sempre qualche forma di modificatore di accesso anche se non è impostato.

static modificatore

Il modificatore statico su una classe significa che la classe non può essere istanziata e che tutti i suoi membri sono statici. Un membro statico ha una versione indipendentemente dal numero di istanze del suo tipo allegato create.

Una classe statica è sostanzialmente la stessa di una classe non statica, ma c'è una differenza: una classe statica non può essere istanziata esternamente. In altre parole, non è possibile utilizzare la nuova parola chiave per creare una variabile del tipo di classe. Poiché non esiste alcuna variabile di istanza, è possibile accedere ai membri di una classe statica utilizzando il nome della classe stessa.

Tuttavia, esiste una cosa come un costruttore statico . Qualsiasi classe può avere una di queste, comprese le classi statiche. Non possono essere chiamati direttamente e non possono avere parametri (diversi dai parametri di tipo sulla classe stessa). Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima della creazione della prima istanza o del riferimento a qualsiasi membro statico. Somiglia a questo:

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

    public static string Bar { get; set; }
}

Le classi statiche sono spesso usate come servizi, puoi usarle così:

MyStaticClass.ServiceMethod(...);

17
E puoi avere metodi statici in classi non statiche, giusto?
John Bubriski

14
Sì, si sarebbero comportati allo stesso modo del mio esempio.
mbillard,

7
Che cosa significa il termine "assembly" in questo contesto?
Jonathan Gleason,

1
@gotoVoid Qualunque cosa tu abbia cercato su Google non è corretta. Secondo MSDN , interno protetto significa che "è possibile accedere al tipo o al membro da qualsiasi codice nell'assembly in cui è dichiarato o dall'interno di una classe derivata in un altro assembly".
Kevin,

2
Qual è la differenza tra Protetto e Protetto privato? Per me, sembra che siano entrambi uguali ..
goofyui,

161

Una panoramica grafica (riepilogo in breve)

Visibilità

Poiché le classi statiche sono sigillate, non possono essere ereditate (tranne che da Object), quindi la parola chiave protetta non è valida per le classi statiche.



Per i valori predefiniti se non si mette in primo piano il modificatore di accesso, vedere qui:
Visibilità predefinita per classi e membri C # (campi, metodi, ecc.)?

Non nidificati

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

Nidificato:

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

Inoltre, c'è una parola chiave sigillata, che rende una classe non ereditabile.
Inoltre, in VB.NET, le parole chiave a volte sono diverse, quindi qui un cheat-sheet:

VB vs. CS equivalenti


1
@ ᴇn BᴇrtiL: Sei sicuro? Una classe derivata in un assembly diverso?
Stefan Steiger,

classe derivata nella stessa assemblea che possiamo, diversa non possiamo. Pensavo intendessi come nella stessa assemblea ...
Arun Bertil

1
@ ᴇn BᴇrtiL: Hmm, giusto, questo dovrebbe effettivamente essere tratteggiato.
Stefan Steiger,

1
Penso che ci sia un errore nel diagramma. Se interno è usato per una classe, la classe può essere derivata da un'altra classe nello stesso assembly. Inoltre, se il modificatore interno viene utilizzato su una proprietà, è possibile accedere a questa proprietà nella classe derivata nello stesso assembly. Forse il diagramma è corretto perché c'è un "sì" sotto "contenente assembly", ma può essere frainteso perché c'è un "no" sotto "classi derivate".
AH.

160

Pubblico : se riesci a vedere la classe, puoi vedere il metodo

Privato : se fai parte della classe, puoi vedere il metodo, altrimenti no.

Protetto : uguale a privato, inoltre tutti i discendenti possono anche vedere il metodo.

Statico (classe) - Ricorda la distinzione tra "Classe" e "Oggetto"? Dimentica tutto ciò. Sono gli stessi con "statico" ... la classe è l'istanza unica di se stessa.

Statico (metodo) - Ogni volta che si utilizza questo metodo, avrà un frame di riferimento indipendente dall'istanza effettiva della classe di cui fa parte.


1
Non puoi avere metodi statici in una classe non statica?
John Bubriski

1
Sì, ma stavo parlando di una classe statica. Ho aggiunto una voce separata per descrivere i metodi statici. Grazie per la cattura.
JosephStyons,

2
"Oggetto" potrebbe non essere un buon termine qui quando si parla di C #, poiché il tipo di base per tutte le classi è System.Object . 'Istanza' sarebbe una parola migliore, o 'oggetto' (minuscola 'O').
lesderid,

@lesderid 'object' è un alias di 'System.Object', usarlo potrebbe anche essere fonte di confusione. "istanza" sarebbe meglio, immagino :)
dpp,

le stesse regole si applicano alle strutture.
gsharp,

35

Ripubblicando i fantastici diagrammi da questa risposta .

Ecco tutti i modificatori di accesso nei diagrammi di Venn, da più limitanti a più promiscui:

private:
inserisci qui la descrizione dell'immagine

private protected: - aggiunto in C # 7.2
inserisci qui la descrizione dell'immagine

internal:
inserisci qui la descrizione dell'immagine

protected:
inserisci qui la descrizione dell'immagine

protected internal:
inserisci qui la descrizione dell'immagine

public:
inserisci qui la descrizione dell'immagine


24

inserisci qui la descrizione dell'immagine

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();
        }
    }
}

1
Non vedo cosa aggiunge questa risposta rispetto alle molte altre risposte degli ultimi cinque anni.
John Saunders,

4
Questa è solo una semplice spiegazione. Poiché le altre risposte sono un po 'confuse e la metà ha risposto :)
Narottam Goyal

4
@ John Saunders: si differenzia separando la visibilità per una classe derivata tra quella classe che si trova nella stessa e quella classe che si trova in un assembly diverso. Inoltre fornisce come ha ottenuto tali informazioni mostrando il suo codice di esempio. Quindi in realtà si aggiunge alle altre risposte. Il suo negromante è stato probabilmente innescato dal mio commento nella mia risposta.
Stefan Steiger,

2
"Classe derivata in un assieme diverso": aggiunge valore al grafico già indicato in un'altra risposta. La differenza è utile soprattutto in caso di "interni protetti"
Nirman

Trovo che questo grafico sia il più semplice per me da capire. Per mantenere questo corrente (con C # 7.2), per aggiungere Private Protected, sarebbe: stessa classe = Yes, stesso assemblaggio, classe derivata = Yes, stesso assemblaggio, qualsiasi classe = NO, diverso assemblaggio, classe derivata = NO, diverso assemblaggio, qualsiasi classe = NO. Un ulteriore suggerimento sarebbe anche quello di non cambiare l'ordine delle parole per protected internal, poiché questo rompe la polmonite dalla risposta di @ user1810087
Intrastellar Explorer

22

Per quanto riguarda la domanda di Nothing

  • I tipi di spazio dei nomi sono interni per impostazione predefinita
  • Qualsiasi membro del tipo, inclusi i tipi nidificati, è privato per impostazione predefinita

15

Ancora un altro approccio visivo dell'attuale modificatore di accesso (C # 7.2). Eventualmente lo schema aiuta a ricordarlo più facilmente
(fare clic sull'immagine per una visualizzazione interattiva).

modificatori di accesso interattivo svg

Fuori dentro

Se fai fatica a ricordare i modificatori di accesso a due parole, ricorda all'esterno .

  • privato protetto : privato esterno (stesso assemblaggio) protetto interno (stesso assemblaggio)
  • interno protetto : esterno protetto (stesso gruppo) interno interno (stesso gruppo)

11

Hmm.

Vedi qui: Modificatori di accesso .

In breve:

Pubblico offre al metodo o al tipo una visibilità completa da altri tipi / classi.

Privato consente solo il tipo contenente il metodo privato / l'accesso alla variabile al metodo privato / la variabile (si noti che le classi nidificate hanno anche accesso alle classi contenenti metodi / variabili privati).

Protetto è simile a privato, tranne che le classi derivate possono accedere anche a metodi protetti.

"Nothing" è equivalente a VB.NET null. Sebbene se ti riferisci a "niente" che significa "nessun modificatore di accesso", dipende, sebbene una regola empirica molto approssimativa (certamente in C #) è che se non specifichi esplicitamente un modificatore di accesso, il metodo / variabile la dichiarazione è generalmente limitata quanto può essere. vale a dire

public class MyClass
{
    string s = "";
}

è effettivamente lo stesso di:

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

L'articolo MSDN collegato offrirà una descrizione completa quando non è stato esplicitamente specificato alcun modificatore di accesso.


8

pubblico - può essere accessibile da chiunque ovunque.
privato - è possibile accedervi solo da con nella classe di cui fa parte.
protetto : è possibile accedervi solo con nella classe o qualsiasi oggetto che eredita al di fuori della classe.

Nulla è come null ma in VB.
Statico significa che hai un'istanza di quell'oggetto, metodo per ogni istanza di quella classe.


4

mmm ...

Statico significa che puoi accedere a quella funzione senza avere un'istanza della classe.

Puoi accedere direttamente dalla definizione della classe.


4

Uno stato di Privato indica che le variabili sono accessibili solo da oggetti della stessa classe. Lo stato protetto estende tale accesso anche ai discendenti della classe.

"dalla tabella sopra possiamo vedere la deferenza tra privato e protetto ... penso che entrambi siano uguali .... quindi quale sia la necessità di quel comando separato"

Controlla il collegamento MSDN per ulteriori informazioni


3

Quei modificatori di accesso specificano dove sono visibili i tuoi membri. Probabilmente dovresti leggerlo. Prendi il link fornito da IainMH come punto di partenza.

I membri statici sono uno per classe e non uno per istanza.


3

Guarda attentamente l'accessibilità delle tue lezioni. Classi e metodi pubblici e protetti sono di default accessibili a tutti.

Inoltre, Microsoft non è molto esplicito nel mostrare modificatori di accesso (parole chiave pubbliche, protette, ecc.) Quando vengono create nuove classi in Visual Studio. Quindi, abbi molta cura e pensa alla tua accessibilità alla tua classe perché è la porta per i tuoi interni di implementazione.


2

Penso che sia legato al buon design OOP. Se sei uno sviluppatore di una biblioteca, vuoi nascondere il funzionamento interno della tua biblioteca. In questo modo, è possibile modificare il funzionamento interno della libreria in un secondo momento. Quindi metti i membri e i metodi di supporto come privati ​​e solo i metodi di interfaccia sono pubblici. I metodi che devono essere sovrascritti devono essere protetti.


1

C # ha in totale 6 modificatori di accesso:

privato : il membro dichiarato con questa accessibilità può essere visibile all'interno del tipo contenitore, non è visibile a nessun tipo derivato, altri tipi nello stesso assieme o tipi all'esterno dell'assieme contenente. vale a dire, l'accesso è limitato al solo tipo contenente.

protetto : il membro dichiarato con questa accessibilità può essere visibile all'interno dei tipi derivati ​​dal tipo contenitore all'interno dell'assieme contenitore e i tipi derivati ​​dal tipo contenitore all'esterno dell'assieme contenitore. vale a dire, l'accesso è limitato ai tipi derivati ​​del tipo contenente.

interno : il membro dichiarato con questa accessibilità può essere visibile all'interno dell'assembly che contiene questo membro, non è visibile a nessun assembly esterno all'assembly contenente. vale a dire, l'accesso è limitato al solo contenimento dell'assemblaggio.

interno protetto : il membro dichiarato con questa accessibilità può essere visibile all'interno dei tipi derivati ​​dal tipo contenitore all'interno o all'esterno dell'assieme contenitore, inoltre è visibile a tutti i tipi all'interno dell'assieme contenitore. vale a dire, l'accesso è limitato al contenimento di tipi assemblati o derivati.

pubblico : il membro dichiarato con questa accessibilità può essere visibile all'interno dell'assembly che contiene questo membro o qualsiasi altro assembly che fa riferimento all'assembly contenente. cioè, l'accesso non è limitato.

C # 7.2 sta aggiungendo un nuovo livello di accessibilità:

privato protetto : il membro dichiarato con questa accessibilità può essere visibile all'interno dei tipi derivati ​​da questo tipo contenente all'interno dell'assieme contenitore. Non è visibile a nessun tipo non derivato dal tipo contenitore o all'esterno dell'assieme contenitore. vale a dire, l'accesso è limitato ai tipi derivati ​​all'interno dell'assieme contenitore.

Sorgente che include un codice di esempio del nuovo modificatore di accesso protetto privato


0

Descrizioni di tutti i modificatori di accesso per C #

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.