In einem unserer Projekte steckt viel Code, der so aussieht:
internal static class Extensions
{
public static string AddFoo(this string s)
{
if (s == null)
{
return "Foo";
}
return $({s}Foo);
}
}
Gibt es einen anderen expliziten Grund als "Es ist einfacher, den Typ später zu veröffentlichen?"
Ich vermute, dass es nur in sehr seltsamen Randfällen (Reflexion in Silverlight) oder überhaupt nicht wichtig ist.
return s + "Foo";
? Der+
Operator kümmert sich nicht um null oder leere Zeichenfolgen.Antworten:
UPDATE: Diese Frage war das Thema meines Blogs im September 2014 . Danke für die tolle Frage!
Selbst innerhalb des Compilerteams selbst gibt es erhebliche Debatten zu dieser Frage.
Zunächst einmal ist es ratsam, die Regeln zu verstehen. Ein öffentliches Mitglied einer Klasse oder Struktur ist ein Mitglied, auf das jeder zugreifen kann, der auf den enthaltenen Typ zugreifen kann . Ein öffentliches Mitglied einer internen Klasse ist also effektiv intern.
Sollten nun bei einer internen Klasse die Mitglieder, auf die Sie in der Versammlung zugreifen möchten, als öffentlich oder intern gekennzeichnet sein?
Meine Meinung ist: Markiere solche Mitglieder als öffentlich.
Ich benutze "public", um zu bedeuten, dass "dieses Mitglied kein Implementierungsdetail ist". Ein geschütztes Mitglied ist ein Implementierungsdetail. Es gibt etwas, das benötigt wird, damit eine abgeleitete Klasse funktioniert. Ein internes Mitglied ist ein Implementierungsdetail. Für etwas anderes in dieser Baugruppe ist das Mitglied erforderlich, damit es ordnungsgemäß funktioniert. Ein öffentliches Mitglied sagt: "Dieses Mitglied repräsentiert die wichtigsten dokumentierten Funktionen, die von diesem Objekt bereitgestellt werden."
Grundsätzlich lautet meine Einstellung: Angenommen, ich habe beschlossen, diese interne Klasse zu einer öffentlichen Klasse zu machen. Dazu möchte ich genau eines ändern : die Zugänglichkeit der Klasse. Wenn das Verwandeln einer internen Klasse in eine öffentliche Klasse bedeutet, dass ich auch ein internes Mitglied in ein öffentliches Mitglied verwandeln muss, dann war dieses Mitglied Teil der öffentlichen Fläche der Klasse und sollte an erster Stelle öffentlich sein.
Andere Leute sind anderer Meinung. Es gibt ein Kontingent, das besagt, dass sie in der Lage sein möchten, einen Blick auf die Erklärung eines Mitglieds zu werfen und sofort zu wissen, ob sie nur aus dem internen Code aufgerufen wird.
Leider klappt das nicht immer gut; Bei einer internen Klasse, die eine interne Schnittstelle implementiert, müssen die implementierenden Mitglieder weiterhin als öffentlich markiert sein, da sie Teil der öffentlichen Oberfläche der Klasse sind .
quelle
public
sehr überzeugend. Allerdings finde ich das "funktioniert nicht immer gut ..." besonders mächtig. Wenn Sie die Konsistenz verlieren, werden alle Vorteile auf einen Blick abgewertet. Aufinternal
diese Weise zu verwenden bedeutet, absichtlich Intuitionen aufzubauen, die manchmal falsch sind. Eine meist richtige Intuition zu haben, ist IMO eine schreckliche Sache für die Programmierung.Wenn dies der
internal
Fall ist , spielt es unter dem Gesichtspunkt der Barrierefreiheit keine Rolle, ob Sie eine Methode markiereninternal
oderpublic
. Es ist jedoch immer noch gut, den Typ zu verwenden, den Sie verwenden würden, wenn die Klasse wärepublic
.Während einige gesagt haben, dass dies Übergänge von
internal
nach erleichtertpublic
. Es dient auch als Teil der Beschreibung der Methode.Internal
Methoden werden normalerweise als unsicher für uneingeschränkten Zugriff angesehen, währendpublic
Methoden als (meistens) freies Spiel angesehen werden.Indem Sie
internal
oderpublic
wie in einerpublic
Klasse verwenden, stellen Sie sicher, dass Sie kommunizieren, welche Art des Zugriffs erwartet wird, und erleichtern gleichzeitig die Arbeit, die erforderlich ist, um die Klassepublic
in Zukunft zu erstellen.quelle
Ich markiere meine Methoden oft in internen Klassen öffentlich statt intern als a) es ist nicht wirklich wichtig und b) ich benutze intern, um anzuzeigen, dass die Methode absichtlich intern ist (es gibt einen Grund, warum ich dies nicht offenlegen möchte Methode in einer öffentlichen Klasse. Wenn ich also eine interne Methode habe, muss ich wirklich verstehen, warum sie intern ist, bevor ich sie in öffentlich umwandle. Wenn ich mich mit einer öffentlichen Methode in einer internen Klasse befasse, muss ich wirklich darüber nachdenken, warum die Klasse ist intern im Gegensatz dazu, warum jede Methode intern ist.
quelle
Ich vermute, dass "es einfacher ist, den Typ später zu veröffentlichen?" ist es.
Die Scoping-Regeln bedeuten, dass die Methode nur als sichtbar ist
internal
- es spielt also keine Rolle, ob die Methoden markiert sindpublic
oder nichtinternal
.Eine Möglichkeit , die in den Sinn kommt , ist , dass die Klasse war öffentlich und wurde später geändert
internal
und der Entwickler nicht die Mühe , alle Verfahrens Zugänglichkeit Modifikatoren zu ändern.quelle
In einigen Fällen kann es auch sein, dass der interne Typ eine öffentliche Schnittstelle implementiert, was bedeutet, dass alle auf dieser Schnittstelle definierten Methoden weiterhin als öffentlich deklariert werden müssen.
quelle
Es ist dasselbe, die öffentliche Methode wird wirklich als intern markiert, da sie sich innerhalb einer internen Klasse befindet, aber sie hat einen Vorteil (wie Sie zu Gast hatten). Wenn Sie die Klasse als öffentlich markieren möchten, müssen Sie weniger Code ändern.
quelle
internal
sagt, dass auf das Mitglied nur innerhalb derselben Assembly zugegriffen werden kann. Andere Klassen in dieser Assembly können auf dasinternal public
Mitglied zugreifen , können jedoch nicht auf einprivate
oderprotected
Mitglied zugreifeninternal
oder nicht.quelle
internal
anstelle von markiertpublic
würden, würde sich ihre Sichtbarkeit nicht ändern. Ich glaube, darum bittet das OP.Ich hatte heute tatsächlich damit zu kämpfen. Bis jetzt hätte ich gesagt, dass alle Methoden markiert werden sollten,
internal
wenn die Klasseinternal
etwas anderes als schlechte Codierung oder Faulheit betrachtet hätte und hätte, insbesondere in der Unternehmensentwicklung; Ich musste jedoch einepublic
Klasse unterordnen und eine ihrer Methoden überschreiben:Die Methode MUSS sein
public
und es hat mich zu dem Gedanken gebracht, dass es wirklich keinen logischen Grund gibt, Methoden sointernal
einzustellen, als ob sie wirklich sein müssten, wie Eric Lippert sagte.Bis jetzt habe ich nie wirklich aufgehört darüber nachzudenken, ich habe es einfach akzeptiert, aber nachdem ich Erics Beitrag gelesen hatte, brachte es mich wirklich zum Nachdenken und nach vielen Überlegungen macht es sehr viel Sinn.
quelle
Es gibt einen Unterschied. In unserem Projekt haben wir viele interne Klassen erstellt, aber wir führen Unit-Tests in einer anderen Assembly durch. In unseren Assembly-Informationen haben wir InternalsVisibleTo verwendet, damit die UnitTest-Assembly die internen Klassen aufrufen kann. Ich habe festgestellt, dass die interne Klasse, wenn sie einen internen Konstruktor hat, aus irgendeinem Grund keine Instanz mit Activator.CreateInstance in der Unit-Test-Assembly erstellen kann. Wenn wir den Konstruktor jedoch in public ändern, die Klasse jedoch noch intern ist, funktioniert dies einwandfrei. Aber ich denke, dies ist ein sehr seltener Fall (wie Eric im ursprünglichen Beitrag sagte: Reflection).
quelle
Ich glaube, ich habe eine zusätzliche Meinung dazu. Zuerst habe ich mich gefragt, wie es sinnvoll ist, in einer internen Klasse etwas öffentlich zu erklären. Dann bin ich hier gelandet und habe gelesen, dass es gut sein könnte, wenn Sie später beschließen, die Klasse in öffentlich zu ändern. Wahr. Also ein Muster, das sich in meinem Kopf gebildet hat: Wenn es das aktuelle Verhalten nicht ändert, dann sei freizügig und erlaube Dinge, die im aktuellen Code-Status keinen Sinn ergeben (und nicht schaden), aber später, wenn du es tust Ändern Sie die Deklaration der Klasse.
So was:
Nach dem oben erwähnten "Muster" sollte dies vollkommen in Ordnung sein. Es folgt der gleichen Idee. Es verhält sich wie eine
private
Methode, da Sie die Klasse nicht erben können. Wenn Sie diesealed
Einschränkung jedoch löschen , ist sie weiterhin gültig: Die geerbten Klassen können diese Methode sehen, was absolut das ist, was ich erreichen wollte. Aber du bekommst eine Warnung:CS0628
oderCA1047
. Bei beiden geht es darum, keineprotected
Mitglieder einersealed
Klasse zu deklarieren . Darüber hinaus habe ich volle Übereinstimmung darüber gefunden, dass es sinnlos ist: Warnung "Geschütztes Mitglied in versiegelter Klasse" (eine Singleton-Klasse)Nach dieser Warnung und der damit verbundenen Diskussion habe ich beschlossen, alles intern oder weniger in einer internen Klasse zu machen, da es mehr dieser Art des Denkens entspricht und wir keine unterschiedlichen "Muster" mischen.
quelle