Was ist in C # der Unterschied zwischen öffentlich, privat, geschützt und ohne Zugriffsmodifikator?

728

Alle meine College - Jahren habe ich mit public, und möchte den Unterschied zwischen wissen public, privateund protected?

Was macht statices auch, wenn man nichts hat?

MrM
quelle

Antworten:

1008

Zugriffsmodifikatoren

Von docs.microsoft.com :

public

Auf den Typ oder das Mitglied kann von jedem anderen Code in derselben Assembly oder einer anderen Assembly zugegriffen werden, die darauf verweist.

private

Auf den Typ oder das Mitglied kann nur über Code in derselben Klasse oder Struktur zugegriffen werden.

protected

Auf den Typ oder das Mitglied kann nur über Code in derselben Klasse oder Struktur oder in einer abgeleiteten Klasse zugegriffen werden.

private protected (hinzugefügt in C # 7.2)

Auf den Typ oder das Mitglied kann nur über Code in derselben Klasse oder Struktur oder in einer abgeleiteten Klasse aus derselben Assembly, jedoch nicht aus einer anderen Assembly zugegriffen werden.

internal

Auf den Typ oder das Mitglied kann von jedem Code in derselben Assembly zugegriffen werden, jedoch nicht von einer anderen Assembly.

protected internal

Auf den Typ oder das Mitglied kann von jedem Code in derselben Assembly oder von jeder abgeleiteten Klasse in einer anderen Assembly zugegriffen werden.

Wenn kein Zugriffsmodifikator festgelegt ist, wird ein Standardzugriffsmodifikator verwendet. Es gibt also immer eine Art Zugriffsmodifikator, auch wenn dieser nicht festgelegt ist.

static Modifikator

Der statische Modifikator für eine Klasse bedeutet, dass die Klasse nicht instanziiert werden kann und dass alle ihre Mitglieder statisch sind. Ein statisches Mitglied hat eine Version, unabhängig davon, wie viele Instanzen seines umschließenden Typs erstellt werden.

Eine statische Klasse ist im Grunde dieselbe wie eine nicht statische Klasse, aber es gibt einen Unterschied: Eine statische Klasse kann nicht extern instanziiert werden. Mit anderen Worten, Sie können das neue Schlüsselwort nicht zum Erstellen einer Variablen des Klassentyps verwenden. Da es keine Instanzvariable gibt, greifen Sie mithilfe des Klassennamens auf die Mitglieder einer statischen Klasse zu.

Es gibt jedoch einen statischen Konstruktor . Jede Klasse kann eine davon haben, einschließlich statischer Klassen. Sie können nicht direkt aufgerufen werden und dürfen keine Parameter haben (außer Typparametern in der Klasse selbst). Ein statischer Konstruktor wird automatisch aufgerufen, um die Klasse zu initialisieren, bevor die erste Instanz erstellt oder auf statische Elemente verwiesen wird. Sieht aus wie das:

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

    public static string Bar { get; set; }
}

Statische Klassen werden häufig als Dienste verwendet. Sie können sie folgendermaßen verwenden:

MyStaticClass.ServiceMethod(...);
mbillard
quelle
17
Und Sie können statische Methoden in nicht statischen Klassen haben, richtig?
John Bubriski
14
Ja, sie würden sich genauso verhalten wie in meinem Beispiel.
mbillard
7
Was bedeutet der Begriff "Versammlung" in diesem Zusammenhang?
Jonathan Gleason
1
@gotoVoid Was auch immer Sie bei Google gesucht haben, ist falsch. Laut MSDN bedeutet "geschützt intern", dass "auf den Typ oder das Mitglied von jedem Code in der Assembly zugegriffen werden kann, in der es deklariert ist, oder von einer abgeleiteten Klasse in einer anderen Assembly".
Kevin
2
Was ist der Unterschied zwischen geschützt und privat geschützt? Für mich klingt es, dass beide gleich sind ..
goofyui
161

Eine grafische Übersicht (Zusammenfassung auf den Punkt gebracht)

Sichtweite

Da statische Klassen versiegelt sind, können sie nicht geerbt werden (außer von Object), sodass das geschützte Schlüsselwort für statische Klassen ungültig ist.



Die Standardeinstellungen, wenn Sie keinen Zugriffsmodifikator voranstellen, finden Sie hier:
Standardsichtbarkeit für C # -Klassen und -Mitglieder (Felder, Methoden usw.)?

Nicht verschachtelt

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

Verschachtelt:

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

Außerdem gibt es das Sealed-Keyword, wodurch eine Klasse nicht vererbbar wird.
Außerdem sind die Schlüsselwörter in VB.NET manchmal unterschiedlich, daher hier ein Spickzettel:

VB vs. CS-Äquivalente

Stefan Steiger
quelle
1
@ ᴀʀᴜn BᴇrtiL: Bist du sicher? Eine abgeleitete Klasse in einer anderen Assembly?
Stefan Steiger
abgeleitete Klasse in der gleichen Versammlung können wir, anders können wir nicht. Ich dachte, Sie meinten wie in der gleichen Versammlung ...
Arun Bertil
1
@ ᴀʀᴜn BᴇrtiL: Hmm, richtig, das sollte eigentlich schraffiert sein.
Stefan Steiger
1
Ich denke, es gibt einen Fehler im Diagramm. Wenn intern für eine Klasse verwendet wird, kann die Klasse von einer anderen Klasse in derselben Assembly abgeleitet werden. Wenn der interne Modifikator für eine Eigenschaft verwendet wird, kann auf diese Eigenschaft auch in der abgeleiteten Klasse in derselben Assembly zugegriffen werden. Vielleicht ist das Diagramm korrekt, weil unter "Assembly enthalten" ein "Ja" steht, aber es kann missverstanden werden, weil unter "abgeleiteten Klassen" ein "Nein" steht.
AH.
160

Öffentlichkeit - Wenn Sie die Klasse sehen können, können Sie die Methode sehen

Privat - Wenn Sie ein Teil von sind der Klasse sind, können Sie die Methode sehen, andernfalls nicht.

Geschützt - Wie Privat, plus alle Nachkommen können die Methode auch sehen.

Statisch (Klasse) - Erinnern Sie sich an die Unterscheidung zwischen "Klasse" und "Objekt"? Vergiss das alles. Sie sind die gleichen wie bei "statisch" ... die Klasse ist die einzige Instanz von sich.

Statisch (Methode) - Wenn Sie diese Methode verwenden, hat sie einen Referenzrahmen, der unabhängig von der tatsächlichen Instanz der Klasse ist, zu der sie gehört.

JosephStyons
quelle
1
Können Sie in einer nicht statischen Klasse keine statischen Methoden haben?
John Bubriski
1
Ja, aber ich habe über eine statische Klasse gesprochen. Ich habe einen separaten Eintrag hinzugefügt, um statische Methoden zu beschreiben. Danke für den Fang.
JosephStyons
2
'Objekt' ist hier möglicherweise kein guter Begriff, wenn es um C # geht, da der Basistyp für alle Klassen System.Object ist . "Instanz" wäre ein besseres Wort oder "Objekt" (Kleinbuchstabe "O").
Lesderid
@lesderid 'object' ist ein Alias ​​von 'System.Object', dessen Verwendung ebenfalls verwirrend sein kann. 'Instanz' wäre besser, denke ich :)
dpp
Gleiches gilt für Strukturen.
Gsharp
35

Reposting der fantastischen Diagramme aus dieser Antwort .

Hier sind alle Zugriffsmodifikatoren in Venn-Diagrammen, von einschränkender bis promiskuitiver:

private::
Geben Sie hier die Bildbeschreibung ein

private protected: - hinzugefügt in C # 7.2
Geben Sie hier die Bildbeschreibung ein

internal::
Geben Sie hier die Bildbeschreibung ein

protected::
Geben Sie hier die Bildbeschreibung ein

protected internal::
Geben Sie hier die Bildbeschreibung ein

public::
Geben Sie hier die Bildbeschreibung ein

Paul
quelle
24

Geben Sie hier die Bildbeschreibung ein

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
quelle
1
Ich sehe nicht, was diese Antwort gegenüber den vielen anderen Antworten der letzten fünf Jahre hinzufügt.
John Saunders
4
Dies ist nur eine einfache Erklärung. Da andere Antworten etwas verwirrend und halb beantwortet sind :)
Narottam Goyal
4
@ John Saunders: Es unterscheidet, indem die Sichtbarkeit für eine abgeleitete Klasse zwischen dieser Klasse in derselben und dieser Klasse in einer anderen Assembly getrennt wird. Außerdem gibt er an, wie er zu diesen Informationen gekommen ist, indem er seinen Beispielcode zeigt. Es ergänzt also tatsächlich die anderen Antworten. Seine Nekromantie wurde wahrscheinlich durch meinen Kommentar in meiner Antwort ausgelöst.
Stefan Steiger
2
"Abgeleitete Klasse in unterschiedlicher Baugruppe" - Dies erhöht den Wert des Diagramms, das bereits in einer anderen Antwort angegeben ist. Der Unterschied ist besonders im Fall von "geschützten internen" hilfreich
Nirman
Ich finde dieses Diagramm für mich am einfachsten zu verstehen. Um dies aktuell zu halten (mit C # 7.2), Private Protectedwäre es: gleiche Klasse = Yes, gleiche Assembly, abgeleitete Klasse = Yes, gleiche Assembly, jede Klasse = NO, unterschiedliche Assembly, abgeleitete Klasse = NO, unterschiedliche Assembly, jede Klasse = NO. Ein zusätzlicher Vorschlag wäre auch, die Wortreihenfolge nicht zu protected internaländern, da dies die Pneumonie von der Antwort von @ user1810087
Intrastellar Explorer
22

In Bezug auf die Frage des Nichts

  • Namespace-Typen sind standardmäßig intern
  • Alle Typmitglieder, einschließlich verschachtelter Typen, sind standardmäßig privat
Leppie
quelle
15

Noch ein visueller Ansatz des aktuellen Zugriffsmodifikators (C # 7.2). Hoffentlich hilft das Schema dabei, sich leichter daran zu erinnern
(klicken Sie auf das Bild, um eine interaktive Ansicht zu erhalten.)

interaktive Zugriffsmodifikatoren svg

Draußen drinnen

Wenn Sie Schwierigkeiten haben, sich an die Zugriffsmodifikatoren mit zwei Wörtern zu erinnern, denken Sie an Außen-Innen .

  • privat geschützt : privat außen (dieselbe Baugruppe) innen geschützt (gleiche Baugruppe)
  • intern geschützt : außen geschützt (dieselbe Baugruppe) innen innen (gleiche Baugruppe)
user1810087
quelle
11

Hmm.

Siehe hier: Zugriffsmodifikatoren .

In einer Nussschale:

Öffentlich gibt der Methode oder dem Typ vollständige Sichtbarkeit von anderen Typen / Klassen.

Privat erlaubt nur dem Typ, der die private Methode / Variable enthält, den Zugriff auf die private Methode / Variable (beachten Sie, dass verschachtelte Klassen auch Zugriff auf die privaten Methoden / Variablen der enthaltenden Klassen haben).

Protected ähnelt privat, außer dass abgeleitete Klassen auch auf geschützte Methoden zugreifen können.

"Nothing" entspricht VB.NET null. Wenn Sie sich auf "nichts" beziehen, was "kein Zugriffsmodifikator" bedeutet, hängt dies davon ab, obwohl eine sehr grobe Faustregel (sicherlich in C #) lautet, dass die Methode / Variable, wenn Sie keinen expliziten Zugriffsmodifikator angeben Die Deklaration ist normalerweise so eingeschränkt wie möglich. dh

public class MyClass
{
    string s = "";
}

ist effektiv das gleiche wie:

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

Der verknüpfte MSDN-Artikel enthält eine vollständige Beschreibung, wenn kein Zugriffsmodifikator explizit angegeben ist.

CraigTP
quelle
8

public - kann von jedem überall abgerufen werden.
privat - kann nur von mit in der Klasse aufgerufen werden, zu der es gehört.
geschützt - kann nur von with in der Klasse oder von Objekten aus aufgerufen werden, die von der Klasse erben.

Nichts ist wie null außer in VB.
Statisch bedeutet, dass Sie eine Instanz dieses Objekts haben, eine Methode für jede Instanz dieser Klasse.

Tony
quelle
4

mmm ...

Statisch bedeutet, dass Sie auf diese Funktion zugreifen können, ohne über eine Instanz der Klasse zu verfügen.

Sie können direkt über die Klassendefinition darauf zugreifen.

gbianchi
quelle
4

Der Status Privat gibt an, dass auf Variablen nur von Objekten derselben Klasse zugegriffen werden kann. Der geschützte Status erweitert diesen Zugriff auch auf Nachkommen der Klasse.

"Aus der obigen Tabelle können wir den Unterschied zwischen privat und geschützt erkennen. Ich denke, beide sind gleich. Also, was ist die Notwendigkeit für diese zwei getrennten Befehle?"

Weitere Informationen finden Sie unter MSDN- Link

Grant Hood
quelle
3

Diese Zugriffsmodifikatoren geben an, wo Ihre Mitglieder sichtbar sind. Sie sollten dies wahrscheinlich nachlesen. Nehmen Sie den von IainMH angegebenen Link als Ausgangspunkt.

Statische Mitglieder sind eins pro Klasse und nicht eins pro Instanz.

jpfollenius
quelle
3

Achten Sie sorgfältig auf Ihre Zugänglichkeit Ihrer Klassen. Öffentliche und geschützte Klassen und Methoden sind standardmäßig für alle zugänglich.

Außerdem zeigt Microsoft beim Erstellen neuer Klassen in Visual Studio nicht sehr explizit Zugriffsmodifikatoren (öffentliche, geschützte usw. Schlüsselwörter) an. Seien Sie also vorsichtig und denken Sie über Ihre Zugänglichkeit Ihrer Klasse nach, da dies die Tür zu Ihren Implementierungsinternalen ist.

Patrick Peters
quelle
2

Ich denke, es hängt mit einem guten OOP-Design zusammen. Wenn Sie Entwickler einer Bibliothek sind, möchten Sie das Innenleben Ihrer Bibliothek verbergen. Auf diese Weise können Sie das Innenleben Ihrer Bibliothek später ändern. Sie setzen Ihre Mitglieder- und Hilfsmethoden also als privat, und nur Schnittstellenmethoden sind öffentlich. Methoden, die überschrieben werden sollten, sollten geschützt werden.

Darius Kucinskas
quelle
1

C # hat insgesamt 6 Zugriffsmodifikatoren:

privat : Das mit dieser Barrierefreiheit deklarierte Mitglied kann innerhalb des enthaltenen Typs sichtbar sein. Es ist für abgeleitete Typen, andere Typen in derselben Assembly oder Typen außerhalb der enthaltenen Assembly nicht sichtbar. Das heißt, der Zugriff ist nur auf den enthaltenen Typ beschränkt.

protected : Das mit dieser Barrierefreiheit deklarierte Mitglied kann innerhalb der vom sichtbaren Typ in der enthaltenden Assembly abgeleiteten Typen und der vom enthaltenden Typ abgeleiteten Typen außerhalb der enthaltenden Baugruppe sichtbar sein. Das heißt, der Zugriff ist auf abgeleitete Typen des enthaltenden Typs beschränkt.

intern : Das mit dieser Barrierefreiheit deklarierte Element kann in der Assembly sichtbar sein, die dieses Mitglied enthält. Es ist für keine Assembly außerhalb der enthaltenen Assembly sichtbar. Das heißt, der Zugriff ist nur auf die Baugruppe beschränkt.

intern geschützt : Das mit dieser Barrierefreiheit deklarierte Mitglied kann innerhalb der Typen angezeigt werden, die vom enthaltenden Typ innerhalb oder außerhalb der enthaltenden Baugruppe abgeleitet wurden. Es ist auch für alle Typen innerhalb der enthaltenden Baugruppe sichtbar. Das heißt, der Zugriff ist auf Assemblys oder abgeleitete Typen beschränkt.

public : Das mit dieser Barrierefreiheit deklarierte Mitglied kann in der Assembly, die dieses Mitglied enthält, oder in jeder anderen Assembly, die auf die enthaltende Assembly verweist, sichtbar sein. dh der Zugang ist nicht beschränkt.

C # 7.2 fügt eine neue Ebene der Barrierefreiheit hinzu:

privat geschützt : Das mit dieser Barrierefreiheit deklarierte Mitglied kann in den von diesem enthaltenden Typ abgeleiteten Typen in der enthaltenden Assembly sichtbar sein. Es ist für keine Typen sichtbar, die nicht vom enthaltenen Typ oder außerhalb der enthaltenen Baugruppe abgeleitet sind. Das heißt, der Zugriff ist auf abgeleitete Typen innerhalb der enthaltenden Assembly beschränkt.

Quelle mit einem Beispielcode des neuen Modifikators für privaten geschützten Zugriff

Baccata
quelle
0

Beschreibungen aller Zugriffsmodifikatoren für C #

Geben Sie hier die Bildbeschreibung ein

snr
quelle