2012-05-18 14 views
9

(Diese Frage ist ein Follow-up zu C# accessing protected member in derived class)C# geschützten Bereich Zugang

ich den folgenden Code-Schnipsel haben:

public class Fox 
{ 
    protected string FurColor; 
    private string furType; 

    public void PaintFox(Fox anotherFox) 
    { 
     anotherFox.FurColor = "Hey!"; 
     anotherFox.furType = "Hey!"; 
    } 
} 

public class RedFox : Fox 
{ 
    public void IncorrectPaintFox(Fox anotherFox) 
    { 
     // This one is inaccessible here and results in a compilation error. 
     anotherFox.FurColor = "Hey!"; 
    } 

    public void CorrectPaintFox(RedFox anotherFox) 
    { 
     // This is perfectly valid. 
     anotherFox.FurColor = "Hey!"; 
    } 
} 
  • Jetzt wissen wir, dass private and protected fields are private and protected for type, not instance.

  • Wir wissen auch, dass Zugriffsmodifikatoren zur Kompilierzeit funktionieren sollten. So

  • , hier ist die Frage - warum kann ich nicht auf das FurColor Feld der Fox Klasseninstanz in RedFox?RedFox ist von Fox abgeleitet, daher weiß der Compiler, dass er Zugriff auf die entsprechenden geschützten Felder hat.

  • Auch, wie Sie in CorrectPaintFox sehen können, kann ich auf das geschützte Feld der Klasseninstanz RedFox zugreifen. Warum kann ich das also nicht von der Klasseninstanz Fox erwarten?

+7

Es gibt einen [Blogbeitrag von Eric Lippert zu diesem Thema] (http://blogs.msdn.com/b/ericlippert/archive/2005/11/09/491031.aspx). –

+1

Warum? Denn so wurde die Sprache spezifiziert: http://msdn.microsoft.com/de-us/library/aa691129 (v = vs.71) .aspx –

Antwort

5

Einfacher Grund:

public void IncorrectPaintFox(Fox anotherFox) 
{ 
    anotherFox = new BlueFox(); 

    // This one is inaccessible here and results in a compilation error. 
    anotherFox.FurColor = "Hey!"; 
} 

Jetzt sind Sie nicht auf den geschützten Bereich innerhalb BlueFox Zugriff deshalb, da der Compiler nicht weiß, was der Laufzeittyp ist, muss es immer mache das zu einem Fehler.

+0

@Cicada - danke, aktualisiert –

+0

+1 Menschen immer über Geschwisterklassen vergessen ... –

2

Um etwas über die akzeptierte Antwort zu erweitern, die Grund der Compiler diese Regel erzwingt, in Bezug auf die viel mehr lax Bedeutung von protected Gegensatz, die PHP hat, liegt daran, dass der Zugriff Sie es möglich machen würde zulassen möchten Lassen Zerlegen Sie die Invarianten einer Klasse, indem Sie die definierten Schutzstufen umgehen. (Natürlich ist dies immer möglich, z. B. über Reflection, aber der Compiler macht es zumindest schwierig, zufällig zu machen).

Das Problem ist, dass nur zu wissen, dass ein Objekt a Fox nicht macht es sicher für Sie mit seinen internen Abläufen zu interagieren, weil es möglicherweise nicht tatsächlich ein Fox bei Laufzeit sein. Betrachten Sie diese Klassen:

public class Fox 
{ 
    protected Color FurColor; 
} 

public class RedFox 
{ 
    public RedFox() 
    { 
    this.FurColor = Color.Red; 
    } 
} 

public class ArcticFox 
{ 
    public ArcticFox() 
    { 
    this.FurColor = Color.White; 
    } 
} 

Was Sie fordern für den Compiler ist die folgende Methode zu ermöglichen, vorausgesetzt, es ist auf der RedFox Klasse definiert wurde:

public void PaintFoxRed (Fox fox) 
{ 
    fox.FurColor = Color.Red; 
} 

Aber wenn das legal waren, konnte ich tun dies:

RedFox a = new RedFox(); 
Fox b = new ArcticFox(); 
a.PaintFoxRed(b); 

Mein ArcticFox ist jetzt rot trotz der Klasse selbst erlaubt sich nur weiß zu sein.