Was bedeutet der geplante "privat geschützte" C # -Zugriffsmodifikator?

133

Als Teil der Roslyn- Dokumentation auf GitHub gibt es eine Seite mit dem Namen Implementierungsstatus für Sprachfunktionen mit geplanten Sprachfunktionen für C # und VB.

Eine Funktion, um die ich mich nicht kümmern konnte, war der private protectedZugriffsmodifikator:

private protected string GetId() {  } 

Es gibt auch eine Seite mit C # Language Design Notes , auf der viele neue Funktionen erläutert werden, jedoch nicht diese.

Eric Lippert sagte in einem Kommentar :

Ihr Fehler besteht darin, die Modifikatoren als zunehmende Einschränkungen zu betrachten. Die Modifikatoren verringern tatsächlich immer die Einschränkungen. Denken Sie daran, dass die Dinge standardmäßig "privat" sind. Nur durch Hinzufügen von Modifikatoren werden diese weniger eingeschränkt.

Was bedeutet das private protected? Wann könnte ich es benutzen?

Kobi
quelle
2
Beachten Sie, dass Informationen dazu in den Designhinweisen zur VB-Sprache enthalten sind .
Jesse Good
3
Es ist eine Zuordnung zu MethodAttributes.FamANDAssem. C # hat eine seltsame Zuordnung von intern , es verwendet (Private | FamANDAssem). Und interne geschützte Karten zu (Privat | Familie). Die CLR-Attribute sind seltsam.
Hans Passant
22
Diese vorgeschlagene Funktion macht meinen Kommentar falsch.
Eric Lippert
Das C # -Design-Team hat eine Umfrage mit vorgeschlagener alternativer Syntax für diese Funktion veröffentlicht. Einige von ihnen sind interessant, wie protected & internal, assembly protectedoder proternal(ich hoffe , einige dieser Witze sind). Es gibt auch den Diskussionsthread mit einigen schönen Einsichten.
Kobi
1
Das Feature ist jetzt im Implementierungsstatus des Sprach-Features als zurückgezogen markiert! Persönlich mag ich die Idee dieser Zugriffsebene und ich denke, dass es eine nützliche Funktion ist. Ich möchte den geschützten Code verwenden, um meinen Code gemäß dem Klassendesign zu halten, aber ich möchte nicht, dass andere Hacky-Sublasses schreiben, die Zugriff auf diese Mitglieder erhalten. IMO die beste Lösung wäre, wenn wir schreiben könnten protected | internalundprotected & internal
Felix Keil

Antworten:

98

Laut " Professional C # 2008 " von De Bill Evjen und Jay Glynn, Seite 1699:

privat geschützt - "nur abgeleitete Typen innerhalb der aktuellen Assembly"

C ++ / CLI verfügt über eine ähnliche Funktion: Definieren und Verwenden von Klassen und Strukturen (C ++ / CLI)> Sichtbarkeit von Mitgliedern :

private protected-oder- protected private- Das Mitglied ist innerhalb der Versammlung geschützt, aber außerhalb der Versammlung privat.

Gogutz
quelle
72
Also ist es "geschützt und intern" statt "geschützt oder intern"?
user541686
2
Wird es nun möglich sein, dass ein Mitglied, auf das abgeleitete Klassen zugreifen können, Dinge vom internalTyp akzeptiert oder zurückgibt, ohne dass das Mitglied selbst für alles in der Assembly verfügbar sein muss?
Supercat
Vielen Dank! Daran habe ich nicht gedacht. Ich habe tatsächlich Fälle, in denen ich diesen Modifikator verwendet hätte und auf die ich zurückgegriffen habe internal.
Kobi
3
Das Vorhandensein dieses Vorschlags / Merkmals scheint darauf hinzudeuten, dass die internalSichtbarkeit (in Bezug auf den Ort, an dem die Klasse definiert ist) wirklich orthogonal zu public/ protected/ privateSichtbarkeit (in Bezug auf Vererbung) ist und dass dies möglicherweise internalein eigener Modifikator sein sollte, der von public/ protected/ getrennt ist private.
jpmc26
1
@jww - Ich bin nicht sehr vertraut mit Java, aber soweit ich weiß, packageähnelt Java eher dem Namespace in C #.
Gogutz
187

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

Kobi
quelle
3
Quellbild: Access Modifiers.pdn . Ich habe das treffend benannte Paint.Net verwendet .
Kobi
9
Wo waren diese Diagramme mein ganzes Leben lang (C #)? Sie sind ausgezeichnet - danke!
Jon Peterson
28

Dies dient lediglich dazu, ein Diagramm (erstellt mit http://ashitani.jp/gv/ ) der verschiedenen Eingabehilfen bereitzustellen (Bilder passen nicht in Kommentare).

Digraphendiagramm der C # -Zugriffsebenen

Jeder Pfeil bedeutet "ist restriktiver als".

Die CLR - Namen sind Private, FamilyANDAssembly, Assembly, Family, FamilyORAssembly, Public.


Viel später bearbeitet: Es stellte sich heraus, dass diese nette neue Zugriffsebene (mit einem wirklich schlechten Namen) schließlich nicht in C # 6.0 enthalten war. Es wird nur von C # 7.2 unterstützt (und ich sehe, dass Sie Ihre Frage "Tags" aktualisiert haben).

Jeppe Stig Nielsen
quelle
Es könnte nur ich sein, aber die Pfeile scheinen in die Richtung "weniger restriktiv als" zu gehen.
Acarlon
4
@acarlon Ja, also a → bim Diagramm bedeutet " aist restriktiver als b", also können Sie den Pfeil "lesen" als "ist restriktiver als" (das habe ich zu erklären versucht), also zeigt der Pfeil am wenigsten restriktiv ". Richtung". Die entgegengesetzte Konvention für die Pfeile hätte übrigens genauso gut sein können, aber ich musste eine Konvention wählen.
Jeppe Stig Nielsen
10

Es ist nur eine Vermutung, aber von einem Namen könnte man vermuten, dass es eine eingeschränktere Version von protectedist (oder eine entspanntere Version von, privatewenn Sie es wünschen). Und nur eine vernünftige Variante beschränkt das protectedVerhalten auf die Montage.

Mögliche Verwendung: Dann möchten Sie protectedfür die interne Implementierung, aber nicht für externe Zwecke (und Sie möchten die Klasse nicht versiegeln).

PS Es gab es immer in CLR, aber nicht in C # . Es ist eine Kombination aus protected und internal , Zitat:

CLR unterstützt auch den Zugriffstyp "Familie und Baugruppe". Dies bedeutet, dass auf die Methode innerhalb des deklarierenden Typs, des verschachtelten und des abgeleiteten Typs zugegriffen werden kann, jedoch nur, wenn sie in derselben Assembly deklariert sind. Nun, anscheinend hat das C # -Team dies nicht als sehr nützliche Funktion angesehen, daher wird es in dieser Sprache nicht unterstützt.

Petr Abdulin
quelle
+1 für den CLR-Kommentar - Ich verbringe heutzutage so viel Zeit in C # und so wenig in den anderen .NET-Sprachen, dass ich manchmal vergesse, dass sie nicht dasselbe sind.
Brichins
@DarrelHoffman danke fürs beachten! Ich habe meine Gedanken hier ein wenig durcheinander gebracht)
Petr Abdulin
5

"Kann sein" ist nur für Unterklassen sichtbar, die sich in derselben Assembly befinden. Dies macht es ein wenig eingeschränkt als protected.

Mehmet Ataş
quelle
1

Siehe die Spezifikation für die "privat geschützte" Funktion:

Die intuitive Bedeutung von privat geschützt ist „innerhalb dieser Assembly durch Typen zugänglich, die von der enthaltenden Klasse abgeleitet sind“.

Julien Couvreur
quelle