C # 7.2 führt den privaten geschützten Modifikator ein .
Ich habe den Zugriff auf Felder mit Eigenschaften immer geschützt und den Zugriff über die Get / Set-Methoden ermöglicht, da ich normalerweise nicht möchte, dass der interne Status meines Objekts durch etwas anderes als meine eigene Klasse geändert wird.
Ich versuche zu verstehen, warum das C # -Sprachteam diese Funktion hinzugefügt hat. Nach einer umfangreichen Suche auf Google und dem Lesen und Ansehen der "Was ist neu" -Medien (ich habe die Pressemitteilung , Details und Videos von Mads Torgerson gesehen ) bin ich immer noch nicht klüger.
Für mich scheint dies einem Entwickler zu ermöglichen, das Liskov-Substitutionsprinzip zu brechen, aber dies kann daran liegen, dass ich nicht verstehe, warum diese Funktion jetzt existiert.
Ich verstehe, wie es verwendet werden kann, nur nicht warum - kann jemand bitte ein reales Verwendungsbeispiel anstelle des erfundenen in den MSDN-Dokumenten bereitstellen?
protected
aber mit einem wichtigen Unterschied: Wenn eine Klasse davon abgeleitet ist, aber in einer anderen Assembly, kann sie nicht auf dieses Mitglied zugreifen, obwohlprotected
es nicht auf dieselbe Assembly beschränkt ist.Query
.private protected
würde mir genau das geben was ich will.Antworten:
Vor C # 7.2 hatten wir
protected internal
Modifikator. Dies bedeutet wirklich, dass geschützt ODER intern ist, dh, das MitgliedA
ist für untergeordnete Klassen und auch für jede Klasse in der aktuellen Assembly zugänglich, selbst wenn diese Klasse kein Kind der Klasse istA
(daher wird die durch "geschützt" implizierte Einschränkung gelockert).private protected
bedeutet wirklich geschützt und intern. Das heißt, das Mitglied ist nur für untergeordnete Klassen zugänglich, die sich in derselben Assembly befinden, nicht jedoch für untergeordnete Klassen, die sich außerhalb der Assembly befinden (daher wird die durch "geschützt" implizierte Einschränkung eingeschränkt - wird noch restriktiver). Dies ist nützlich, wenn Sie eine Klassenhierarchie in Ihrer Assembly erstellen und nicht möchten, dass untergeordnete Klassen aus anderen Assemblys auf bestimmte Teile dieser Hierarchie zugreifen.Wir können annehmen Beispiel , dass Jon Skeet vorgesehen in den Kommentaren . Angenommen, Sie haben Klasse
public class MyClass { }
Und Sie möchten in der Lage sein, nur in der aktuellen Assembly davon zu erben, möchten aber nicht zulassen, dass diese Klasse direkt instanziiert wird, außer innerhalb dieser Klassenhierarchie.
Eine Vererbung nur innerhalb der aktuellen Baugruppe kann mit einem internen Konstruktor erreicht werden
public class MyClass { internal MyClass() { } }
Das Verhindern einer direkten Instanziierung mit Ausnahme der aktuellen Klassenhierarchie kann mit dem geschützten Konstruktor erreicht werden:
public class MyClass { protected MyClass() { } }
Und um beides zu bekommen, benötigen Sie einen
private protected
Konstruktor:public class MyClass { private protected MyClass() { } }
quelle
protected
das "ähnlicher" ist alsprotected internal
(sehr verwirrender Zugriffsmodifikator, weil die öffentliche Versammlung weise ist). Derprotected
Zugriffsmodifikator hat denselben Vertrag: Nur innerhalb desselben Typs oder der daraus abgeleiteten Typen zugänglich. Der Umfang ist jedoch nicht auf diese Baugruppe beschränktprivate internal
. Wenn es sich also um ein Mitglied handeltprotected
, müssen Sie jedoch vermeiden, dass es von außerhalb dieser benötigten Assembly zugänglich istprivate protected
.Für Zwei-Wort- Zugriffsmodifikatoren habe ich dieses Konzept - der erste Accessor bezieht sich auf eine andere Assembly, der zweite auf die Assembly, in der er definiert wurde.
intern geschützt
geschützt in einer anderen Assembly: nur in den untergeordneten Klassen zugänglich.
intern in der aktuellen Assembly: Zugriff für alle in der aktuellen Assembly.
privat geschützt
quelle
Nehmen wir an, Sie haben eine interne Klasse namens
SomeHelper
, die Sie als Teil der Implementierung einer öffentlichen abstrakten Basisklasse verwenden möchten:public abstract class Test { // Won't compile because SomeHelper is internal. protected SomeHelper CreateHelper() { return new SomeHelper(); } public int Func(int x) { var helper = CreateHelper(); return helper.DoSomething(x); } } internal class SomeHelper { public virtual int DoSomething(int x) { return -x; } }
Dies wird nicht kompiliert, da keine geschützte Methode einen internen Typ zurückgeben kann. Ihre einzige
SomeHelper
Möglichkeit besteht darin, diese nicht zu verwenden oderSomeHelper
öffentlich zu machen .(Sie könnten
SomeHelper
eine geschützte innere Klasse von erstellenTest
, aber das funktioniert nicht, wennSomeHelper
es für andere Klassen vorgesehen ist, die nicht von der Basisklasse abgeleitet sind.)Mit der Einführung der
private protected
Funktion können Sie Folgendes deklarierenCreateHelper()
:private protected SomeHelper CreateHelper() { return new SomeHelper(); }
Jetzt wird es kompiliert und Sie müssen Ihre Interna nicht mehr verfügbar machen.
quelle
SomeHelper
alsprotected
innere Klasse von delcareTest
, dann wird es kompiliert (über "Ihr einziger Rückgriff ...").SomeHelper
natürlich nicht "auf diese Weise" verwendet, was ich wirklich gemeint habe).internal
logisch zu kennzeichnenprotected
und Codierungsdisziplin zu verwenden, um nicht von außerhalb der Hierarchie auf sie zuzugreifen. Das in der Antwort von @Evk bereitgestellte Beispiel verursachte niemals Probleme, da es gelöst wird, indem die Basisklasseabstract
nur mitinternal
Konstruktoren erstellt wird.