W języku C #, jaka jest różnica między publicznym, prywatnym, chronionym i nie posiadającym modyfikatora dostępu?

728

Wszystkie lata mojej uczelni używam public, a chcieliby, aby znać różnicę między public, privatei protected?

Co też robi static, gdy nie ma nic?

MrM
źródło

Odpowiedzi:

1007

Modyfikatory dostępu

Od docs.microsoft.com :

public

Dostęp do typu lub elementu można uzyskać za pomocą dowolnego kodu w tym samym zestawie lub innym zestawie, który się do niego odwołuje.

private

Dostęp do typu lub elementu można uzyskać tylko za pomocą kodu w tej samej klasie lub strukturze.

protected

Dostęp do typu lub elementu można uzyskać tylko za pomocą kodu w tej samej klasie lub strukturze lub w klasie pochodnej.

private protected (dodano w C # 7.2)

Dostęp do typu lub elementu można uzyskać tylko za pomocą kodu w tej samej klasie lub strukturze lub w klasie pochodnej z tego samego zestawu, ale nie z innego zestawu.

internal

Dostęp do typu lub elementu można uzyskać za pomocą dowolnego kodu w tym samym zestawie, ale nie z innego zestawu.

protected internal

Dostęp do typu lub elementu można uzyskać za pomocą dowolnego kodu w tym samym zestawie lub dowolnej klasy pochodnej w innym zestawie.

Gdy nie jest ustawiony żaden modyfikator dostępu, używany jest domyślny modyfikator dostępu. Tak więc zawsze istnieje jakaś forma modyfikatora dostępu, nawet jeśli nie jest ustawiona.

static modyfikator

Modyfikator statyczny w klasie oznacza, że ​​nie można utworzyć instancji klasy i że wszystkie jej elementy są statyczne. Element statyczny ma jedną wersję, niezależnie od liczby utworzonych wystąpień typu otaczającego.

Klasa statyczna jest w zasadzie taka sama jak klasa niestatyczna, ale jest jedna różnica: klasy statycznej nie można utworzyć instancji zewnętrznej. Innymi słowy, nie można użyć nowego słowa kluczowego do utworzenia zmiennej typu klasy. Ponieważ nie ma zmiennej instancji, dostęp do członków klasy statycznej można uzyskać, używając samej nazwy klasy.

Istnieje jednak coś takiego jak konstruktor statyczny . Każda klasa może mieć jedną z nich, w tym klasy statyczne. Nie można ich wywoływać bezpośrednio i nie mogą mieć parametrów (innych niż parametry dowolnego typu w samej klasie). Konstruktor statyczny jest wywoływany automatycznie w celu zainicjowania klasy przed utworzeniem pierwszej instancji lub odwołaniem się do dowolnego elementu statycznego. Wygląda tak:

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

    public static string Bar { get; set; }
}

Klasy statyczne są często używane jako usługi, możesz z nich korzystać w następujący sposób:

MyStaticClass.ServiceMethod(...);
Mbillard
źródło
17
I możesz mieć metody statyczne w klasach niestatycznych, prawda?
John Bubriski
14
Tak, zachowaliby się tak samo jak w moim przykładzie.
mbillard
7
Co w tym kontekście oznacza termin „zgromadzenie”?
Jonathan Gleason,
1
@gotoVoid Cokolwiek wyszukiwałeś w Google jest niepoprawne. Według MSDN chronione wewnętrzne oznacza, że ​​„do typu lub elementu można uzyskać dostęp za pomocą dowolnego kodu w zestawie, w którym jest zadeklarowany, lub z klasy pochodnej w innym zestawie”.
Kevin,
2
Jaka jest różnica między ochroną a ochroną prywatności? Dla mnie brzmi to tak samo ...
goofyui,
161

Przegląd graficzny (podsumowanie w pigułce)

Widoczność

Ponieważ klasy statyczne są zapieczętowane, nie można ich dziedziczyć (z wyjątkiem Object), więc słowo kluczowe protected jest niepoprawne w klasach statycznych.



Aby zobaczyć ustawienia domyślne, jeśli nie umieścisz przed sobą modyfikatora dostępu, zobacz tutaj:
Domyślna widoczność dla klas C # i elementów (pól, metod itp.)?

Nie zagnieżdżone

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

Zagnieżdżone:

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

Są też słowa kluczowe zapieczętowane, przez co klasa nie jest dziedziczna.
Ponadto w VB.NET słowa kluczowe są czasami różne, więc tutaj ściągawka:

VB vs. odpowiedniki CS

Stefan Steiger
źródło
1
@ ᴇn BᴇrtiL: Jesteś pewien? Klasa pochodna w innym zestawie?
Stefan Steiger
wyprowadziliśmy klasę w tym samym zestawie, w którym możemy, inaczej nie możemy. Myślałem, że masz na myśli jak w tym samym zestawie ...
Arun Bertil
1
@ ᴇn BᴇrtiL: Hmm, tak, to powinno się wykluć.
Stefan Steiger,
1
Myślę, że na schemacie jest błąd. Jeśli dla klasy używane jest wewnętrzne, klasa może być wyprowadzona przez inną klasę w tym samym zestawie. Również jeśli wewnętrzny modyfikator jest użyty we właściwości, do tej właściwości można również uzyskać dostęp w klasie pochodnej w tym samym zestawie. Być może schemat jest poprawny, ponieważ w „zawierającym asembler” występuje „tak”, ale może być źle zrozumiany, ponieważ w „klasach pochodnych” występuje „nie”.
AH.
160

Publiczny - jeśli widzisz klasę, możesz zobaczyć metodę

Prywatne - Jeśli jesteś częścią tej klasy, a następnie można zobaczyć sposób, w przeciwnym razie nie.

Chroniony - taki sam jak prywatny, a także wszyscy potomkowie mogą również zobaczyć metodę.

Statyczny (klasa) - pamiętasz rozróżnienie między „klasą” a „przedmiotem”? Zapomnij o tym wszystkim. Są takie same z „statycznym”… klasa jest jedyną instancją samego siebie.

Statyczna (metoda) - Za każdym razem, gdy użyjesz tej metody, będzie ona mieć ramkę odniesienia niezależną od faktycznego wystąpienia klasy, której jest częścią.

JosephStyons
źródło
1
Czy nie możesz mieć metod statycznych w klasie niestatycznej?
John Bubriski
1
Tak, ale mówiłem o klasie statycznej. Dodałem osobny wpis, aby opisać metody statyczne. Dzięki za haczyk.
JosephStyons
2
„Obiekt” może nie być tutaj dobrym określeniem w języku C #, ponieważ typem podstawowym dla wszystkich klas jest System.Object . „Instancja” byłaby lepszym słowem lub „przedmiotem” (małe litery „O”).
lesderid
@lesderid „object” to alias „System.Object”, używanie go również może być mylące. „instancja” byłaby lepsza, jak sądzę :)
dpp
te same zasady dotyczą struktur.
gsharp
35

Przesłanie niesamowitych diagramów z tej odpowiedzi .

Oto wszystkie modyfikatory dostępu na diagramach Venna, od bardziej ograniczających do bardziej wyuzdanych:

private:
wprowadź opis zdjęcia tutaj

private protected: - dodano w C # 7.2
wprowadź opis zdjęcia tutaj

internal:
wprowadź opis zdjęcia tutaj

protected:
wprowadź opis zdjęcia tutaj

protected internal:
wprowadź opis zdjęcia tutaj

public:
wprowadź opis zdjęcia tutaj

Paweł
źródło
24

wprowadź opis zdjęcia tutaj

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
źródło
1
Nie rozumiem, co ta odpowiedź dodaje do wielu innych odpowiedzi z ostatnich pięciu lat.
John Saunders
4
To tylko proste wyjaśnienie. Ponieważ inne odpowiedzi są nieco mylące, a połowa odpowiedziała :)
Narottam Goyal
4
@John Saunders: Różni się, oddzielając widoczność klasy pochodnej między klasą będącą w tej samej klasie a klasą należącą do innego zestawu. Dodatkowo zapewnia, w jaki sposób dotarł do tych informacji, pokazując swój przykładowy kod. Więc faktycznie dodaje się do innych odpowiedzi. Jego nekromancję prawdopodobnie wywołał mój komentarz w mojej odpowiedzi.
Stefan Steiger,
2
„Klasa pochodna w innym zestawie” - dodaje wartości do wykresu podanego już w innej odpowiedzi. Różnica jest pomocna zwłaszcza w przypadku „chronionego wewnętrznego”
Nirman,
Uważam, że ten wykres jest dla mnie najłatwiejszy do zrozumienia. Aby utrzymać ten bieżący (z C # 7.2), dodać Private Protected, byłoby to: ta sama klasa = Yes, ten sam zestaw, klasa pochodna = Yes, ten sam zestaw, dowolna klasa = NO, inny zestaw, klasa pochodna = NO, inny zestaw, dowolna klasa = NO. Dodatkową sugestią byłoby również, aby nie zmieniać kolejności słów protected internal, ponieważ łamie to pneumonię z odpowiedzi @ user1810087
Intrastellar Explorer
22

Odnośnie pytania o nic

  • Typy przestrzeni nazw są domyślnie wewnętrzne
  • Każdy typ elementu, w tym typy zagnieżdżone, są domyślnie prywatne
leppie
źródło
15

Jeszcze inne podejście wizualne obecnego modyfikatora dostępu (C # 7.2). Mam nadzieję, że schemat pomaga łatwiej zapamiętać
(kliknij obraz, aby wyświetlić interaktywny widok).

interaktywne modyfikatory dostępu svg

Na zewnątrz wewnątrz

Jeśli masz problem z zapamiętaniem dwuznacznych modyfikatorów dostępu, pamiętaj o tym, że jesteś na zewnątrz .

  • prywatny chroniony : prywatny na zewnątrz (ten sam zespół) chroniony wewnątrz (ten sam zespół)
  • chroniony wewnętrzny : chroniony na zewnątrz (ten sam zespół) wewnętrzny wewnątrz (ten sam zespół)
użytkownik1810087
źródło
11

Hmm

Zobacz tutaj: Modyfikatory dostępu .

W skrócie:

Publiczny daje metodzie lub typowi pełną widoczność z innych typów / klas.

Prywatny pozwala tylko typowi zawierającemu prywatną metodę / zmienną dostęp do prywatnej metody / zmiennej (zwróć uwagę, że zagnieżdżone klasy mają również dostęp do zawierających klasy prywatnych metod / zmiennych).

Protected jest podobny do prywatnego, z tym że klasy pochodne mogą również uzyskać dostęp do metod chronionych.

„Nic” jest odpowiednikiem VB.NET dla null. Chociaż jeśli mówisz o „niczym”, co oznacza „brak modyfikatora dostępu”, to zależy, chociaż bardzo surową zasadą (z pewnością w języku C #) jest to, że jeśli nie określisz wyraźnie modyfikatora dostępu, metoda / zmienna deklaracja jest zwykle tak ograniczona, jak to tylko możliwe. to znaczy

public class MyClass
{
    string s = "";
}

jest faktycznie taki sam jak:

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

Połączony artykuł MSDN będzie oferował pełny opis, gdy nie ma wyraźnie określonego modyfikatora dostępu.

CraigTP
źródło
8

publiczny - może być dostępny dla każdego w dowolnym miejscu.
prywatny - dostępny tylko z poziomu w klasie, której jest częścią.
chroniony - można uzyskać do niego dostęp wyłącznie z klasy lub dowolnego obiektu dziedziczącego poza klasę.

Nic nie jest jak zero, ale w VB.
Statyczny oznacza, że ​​masz jedną instancję tego obiektu, metodę dla każdej instancji tej klasy.

Tony
źródło
4

mmm ...

Statyczny oznacza, że ​​możesz uzyskać dostęp do tej funkcji bez posiadania instancji klasy.

Możesz uzyskać dostęp bezpośrednio z definicji klasy.

gbianchi
źródło
4

Status Prywatny wskazuje, że zmienne mogą być dostępne tylko przez obiekty tej samej klasy. Status chroniony rozszerza ten dostęp również na potomków klasy.

„Z powyższej tabeli widać szacunek między prywatnym a chronionym… myślę, że oba są takie same… więc jaka jest potrzeba tych dwóch osobnych poleceń”

Sprawdź łącze MSDN, aby uzyskać więcej informacji

Grant Hood
źródło
3

Te modyfikatory dostępu określają, gdzie członkowie są widoczni. Prawdopodobnie powinieneś to przeczytać. Weź jako punkt wyjścia link podany przez IainMH.

Członkowie statyczni to jeden na klasę, a nie jeden na instancję.

jpfollenius
źródło
3

Uważnie obserwuj dostępność swoich zajęć. Publiczne i chronione klasy i metody są domyślnie dostępne dla wszystkich.

Również Microsoft nie bardzo wyraźnie pokazuje modyfikatory dostępu (słowa kluczowe, publiczne, chronione itp.) Podczas tworzenia nowych klas w Visual Studio. Uważaj więc i pomyśl o dostępności swojej klasy, ponieważ jest to drzwi do wewnętrznych elementów implementacyjnych.

Patrick Peters
źródło
2

Myślę, że jest to związane z dobrym projektem OOP. Jeśli jesteś programistą biblioteki, chcesz ukryć wewnętrzne funkcjonowanie swojej biblioteki. W ten sposób możesz później zmodyfikować wewnętrzne funkcjonowanie biblioteki. Dlatego umieścisz członków i metody pomocnicze jako prywatne, a tylko metody interfejsu są publiczne. Metody, które należy zastąpić, powinny być chronione.

Darius Kucinskas
źródło
1

C # ma w sumie 6 modyfikatorów dostępu:

private : Element zadeklarowany z tą dostępnością może być widoczny w ramach typu zawierającego, nie jest widoczny dla żadnych typów pochodnych, innych typów w tym samym zestawie ani typów poza tym zestawem. tzn. dostęp jest ograniczony tylko do typu zawierającego.

chronione : Element zadeklarowany z tą dostępnością może być widoczny w typach pochodzących z typu zawierającego w zestawie zawierającym, a typy pochodzące z typu zawierającego poza zestawem zawierającym. tzn. dostęp jest ograniczony do pochodnych typów typu zawierającego.

wewnętrzny : Element zadeklarowany z tą dostępnością może być widoczny w zespole zawierającym ten element, nie jest widoczny dla żadnego zestawu poza zespołem zawierającym. tzn. dostęp jest ograniczony do ograniczania się tylko do złożenia.

wewnętrzny chroniony : Element zadeklarowany z tą dostępnością może być widoczny w typach pochodzących z typu zawierającego wewnątrz lub na zewnątrz zestawu zawierającego, jest również widoczny dla wszystkich typów w zestawie zawierającym. tzn. dostęp jest ograniczony do zawierania typów zestawu lub pochodnych.

public : Element zadeklarowany z tą dostępnością może być widoczny w zestawie zawierającym ten element lub w dowolnym innym zestawie, który odwołuje się do zestawu zawierającego. tzn. dostęp nie jest ograniczony.

C # 7.2 dodaje nowy poziom dostępności:

prywatny chroniony : Element zadeklarowany z tą dostępnością może być widoczny w typach pochodzących z tego typu zawierającego w zestawie zawierającym. Nie jest widoczny dla żadnego typu niepochodzącego z typu zawierającego lub na zewnątrz zestawu zawierającego. tzn. dostęp jest ograniczony do typów pochodnych w zestawie zawierającym.

Źródło zawierające przykładowy kod nowego prywatnego modyfikatora dostępu chronionego

Baccata
źródło
0

Wszystkie opisy modyfikatorów dostępu do C #

wprowadź opis zdjęcia tutaj

snr
źródło