C#受保护的字段访问

时间:2012-05-18 20:10:36

标签: c# private encapsulation protected

(此问题是C# accessing protected member in derived class

的后续问题

我有以下代码段:

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!";
    }
}
  • 现在,我们知道private and protected fields are private and protected for type, not instance.

  • 我们也知道访问修饰符应该在编译时工作。

  • 所以,问题是这样 - 为什么我无法访问FurColorFox类实例的RedFox字段? { {1}}派生自RedFox,因此编译器知道它可以访问相应的受保护字段。

  • 此外,正如您在Fox中所看到的,我可以访问CorrectPaintFox类实例的受保护字段。 那么,为什么我不能指望RedFox类实例中的相同内容?

2 个答案:

答案 0 :(得分:5)

简单的理由是:

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

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

现在你没有从BlueFox中访问受保护的字段,因此编译器不知道运行时类型是什么,它必须始终使这个错误。

答案 1 :(得分:2)

要稍微扩展已接受的答案,原因编译器强制执行此规则,而不是PHP具有的protected更宽松的含义,因为允许访问您想要允许通过绕过其定义的保护级别来打破类的不变量。 (当然,这总是可能的,例如通过Reflection,但编译器至少使得偶然很难)。

问题在于只知道某个对象是Fox并不能让您安全地与其内部工作进行交互,因为它可能实际上 {{1} }} 在 运行。考虑这些类:

Fox

你要问的是编译器允许以下方法,假设它是在public class Fox { protected Color FurColor; } public class RedFox { public RedFox () { this.FurColor = Color.Red; } } public class ArcticFox { public ArcticFox () { this.FurColor = Color.White; } } 类上定义的:

RedFox

但如果这是合法的,我可以这样做:

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

我的RedFox a = new RedFox(); Fox b = new ArcticFox(); a.PaintFoxRed(b); 现在是红色的,尽管班级本身只允许自己变白。