C# 受保护的字段访问

本文关键字:访问 字段 受保护 | 更新日期: 2023-09-27 18:34:34

(这个问题是C#访问派生类中受保护成员的后续问题(

我有以下代码片段:

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!";
    }
}
  • 现在,我们知道私有和受保护的字段是私有的,并且受类型保护,而不是实例。

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

  • 所以,这里有一个问题 - 为什么我无法访问 RedFoxFox类实例的 FurColor 字段? RedFox派生自Fox,所以编译器知道它有权访问相应的受保护字段。

  • 另外,正如您在CorrectPaintFox中看到的,我可以访问RedFox类实例的受保护字段。那么,为什么我不能期望Fox类实例也是如此呢?

C# 受保护的字段访问

原因很简单:

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

现在您不是从 BlueFox 中访问受保护的字段,因此由于编译器不知道运行时类型是什么,因此它必须始终将此作为错误。

稍微扩展一下接受的答案,编译器执行此规则的原因,而不是 PHP 具有的更宽松的protected含义,是因为允许您想要允许的访问可以通过绕过其定义的保护级别来打破类的不变量。(当然,这总是可能的,例如通过反射,但编译器至少很难意外地做到这一点(。

问题在于,仅仅知道某个对象是Fox并不能使您安全地与其内部工作进行交互,因为它实际上可能不是一个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);

我的ArcticFox现在是红色的,尽管班级本身只允许自己是白色的。