Öffentliche und interne Mitglieder in einer internen Klasse?

70

Ok, das mag eine etwas dumme Frage sein, und es gibt sicherlich die offensichtliche Antwort, aber ich war neugierig, ob ich hier irgendwelche Feinheiten übersehen habe.

Gibt es einen Unterschied in Bezug auf Sichtbarkeit / Benutzerfreundlichkeit zwischen einem publicin einer internalKlasse internaldeklarierten Mitglied und einem in einer internalKlasse deklarierten Mitglied ?

dh zwischen

internal class Foo
{
    public void Bar()
    {
    }
}

und

internal class Foo
{
    internal void Bar()
    {
    }
}

Wenn Sie die Methode als publicund auch deklariert virtualund dann in einer abgeleiteten Klasse überschrieben haben, ist publicder Grund für die Verwendung dieses Modifikators klar. Ist dies jedoch die einzige Situation ... vermisse ich etwas anderes?

Noldorin
quelle
4
Wenn Sie die Methode als öffentlich und auch virtuell deklariert und dann in einer abgeleiteten Klasse überschrieben haben , die public meeeep ist! : Sie dürfen die Sichtbarkeit nicht erhöhen, nur umgekehrt: Sie können eine abgeleitete Klasse einer öffentlichen Klasse erstellen, die intern (oder sogar verschachtelt und privat) ist
springy76
5
Googler nehmen zur Kenntnis: Diese nahezu doppelte Frage enthält eine weitere besonders gute Antwort.
Michael Richardson

Antworten:

62

Betrachten Sie diesen Fall:

public interface IBar { void Bar(); }
internal class C : IBar
{
    public void Bar() { }
}

Hier kann C.Bar nicht als intern markiert werden. Dies ist ein Fehler, da ein Aufrufer von D.GetBar () auf C.Bar zugreifen kann:

public class D
{
    public static IBar GetBar() { return new C(); } 
}
Eric Lippert
quelle
1
Danke Eric, das ist ein weiterer guter Fall. Die effektive Implementierung der Schnittstelle und die Klassenvererbung sind daher die Gründe dafür, dass entweder der Modifikator publicoder der internalModifikator in einer internalKlasse zugelassen wird. In anderen Fällen scheinen sie gleichwertig zu sein.
Noldorin
9
Eric beantwortet auch eine fast identische Frage unter: stackoverflow.com/a/9302642/398015 In seinem Beitrag gibt es zusätzliche Details, die der obigen Antwort erhebliche Substanz verleihen.
Chris
44

Ein publicMitglied ist immer noch gerade internalin einer internalKlasse.

Von MSDN :

Die Zugänglichkeit eines Mitglieds kann niemals größer sein als die Zugänglichkeit seines enthaltenden Typs. Beispielsweise ist eine in einem internen Typ deklarierte öffentliche Methode nur intern zugänglich

Stellen Sie sich das so vor, ich würde auf eine publicImmobilie zugreifen auf ...? Eine Klasse, die ich nicht sehen kann? :) :)

Erics Antwort ist in diesem Fall sehr wichtig. Wenn sie über eine Schnittstelle verfügbar gemacht wird und nicht direkt, macht sie einen Unterschied. Es hängt nur davon ab, ob Sie sich in dieser Situation mit dem Mitglied befinden, mit dem Sie es zu tun haben.

Nick Craver
quelle
Ja, das war in der Tat genau mein Gedanke, außer in dem Fall, auf den Eric hingewiesen hat (sowie der in meiner ursprünglichen Frage).
Noldorin
Es macht auch einen Unterschied, wenn Sie Reflexion verwenden. Standardmethoden ohne Parameter wie Type.GetMethods () geben nur öffentliche Mitglieder zurück. Und die öffentliche Methode innerhalb der internen Klasse weiß immer noch, dass sie öffentlich ist.
springy76
2
"Die Zugänglichkeit eines Mitglieds kann niemals größer sein als die Zugänglichkeit seines enthaltenden Typs." Während dies in einigen Fällen zutrifft, ist ein publicMitglied einer privateKlasse eindeutig ein größerer Bereich als ein privateMitglied einer privateKlasse (das erstere ist projektweit, das letztere nur eine Klasse).
Deanna
@Deanna ja ... aber das macht die frühere Aussage nicht falsch, Sie vergleichen Peers, nicht Container, damit - wo Dinge zugänglich sind, ändert sich nichts, da Sie von außerhalb der privaten Klasse nicht auf ein öffentliches Mitglied zugreifen können Container.
Nick Craver
2

Nur mit einem anderen Beispiel konfrontiert , wo es ist Unterschied zwischen diesen beiden, wenn sie von XAML in WPF verwendet.

XAML:

<Button Tag="{x:Static vm:Foo+Bar.e1}" />

Code mit internalAufzählung wird erfolgreich kompiliert:

internal class Foo
{
    internal enum Bar
    {
        e1,
        e2,
    }
}

Aber überraschenderweise führt eine Änderung zu einem publicFehler:

internal class Foo
{
    public enum Bar
    {
        e1,
        e2,
    }
}

Das letzte Beispiel führt zu einem Kompilierungsfehler:

Fehler MC3064: Innerhalb des Markups können nur öffentliche oder interne Klassen verwendet werden. Der Typ 'Bar' ist nicht öffentlich oder intern.

Leider kann ich nicht erklären, was publicin diesem Fall falsch ist. Meine Vermutung ist "nur weil WPF so funktioniert". Ändern Sie einfach den Modifikator der verschachtelten Klasse in internal, um Fehler zu beseitigen.

keine Ursache
quelle
Danke dafür! Ich würde nie erraten, was mit meinem XAML
Torvin
1

publicMitglieder einer internalKlasse können publicMitglieder von publicBasisklassen überschreiben und sind daher etwas exponierter ... wenn auch indirekt.


quelle
1

Wenn es um Reflexion geht, ist es wichtig, ob das Mitglied öffentlich ist oder nicht:

Zum Beispiel könnten Sie sogar eine verschachtelte private Klasse an eine WPF-Bindung übergeben, und die Bindung würde wie gewohnt für die öffentlichen Eigenschaften funktionieren.

springy76
quelle