无法从派生 class 访问受保护的成员

Cannot access protected members from a derived class

所以我刚刚发现 C# 编译器的奇怪行为(至少对我而言)。

看看下面的演示代码:

public class Program
{
    public static void Main(string[] args)
    {
        ChildClass c = new ChildClass();
        c.parentInstance = new ChildClass();
        c.ChildPublicMethod();
        Console.ReadKey();
    }
}

public class ParentClass
{
    public ParentClass parentInstance = null;

    protected void ProtectedMethod(string arg)
    {
        Console.WriteLine("Arg=\"{0}\"", arg);
    }

    public void ParentPublicMethod()
    {
        ProtectedMethod("Parent's public method.");
    }
}

public class ChildClass : ParentClass
{
    public void ChildPublicMethod()
    {
        ParentPublicMethod();
        ProtectedMethod("Child's protected method");

        ((ChildClass)parentInstance).ProtectedMethod(
                "A different child's protected method.");
        //parentInstance.ProtectedMethod(
        //      "A different child's protected method."); //Compile time error.
    }

}

ChildClass.ChildPublicMethod()函数中,我希望我可以通过注释掉的代码访问受保护的成员。毕竟,编译器不应该拥有所有必要的信息来判断这是一个安全访问吗?它知道 parentInstanceParentClass 类型,它知道 parentInstance 是从 ParentClass 的后代访问的,那么编译器为什么还要抱怨?

显然,执行演员表似乎可以解决所有问题。 那么这两个调用到底有什么区别呢:?

((ChildClass)parentInstance).ProtectedMethod(
        "A different child's protected method.");
//parentInstance.ProtectedMethod(
//      "A different child's protected method."); //Compile time

事后思考: 我能想到的唯一可能的解释是 C# 编译器需要 100% 确定 parentInstance 确实是 ChildClass 的后代。如果有 class,比如 ChildClass2 : ParentClass,那么从 ChildClass 中访问它的受保护成员是不正确的,因为 ChildClass 不是从 [=24= 派生的].强制转换为 ChildClass 告诉编译器您希望 parentInstance 是一个 ChildClass 实例,而不是 ParentClass.

的其他后代

但是,我发现了另一个问题。 假设我将变量设置为:

c.ParentInstance = new ParentClass();

在这种情况下,ChildClass 无法访问受保护的方法(即使使用强制转换也不行,因为它不能被强制转换为包含受保护方法的任何其他方法)。为什么会这样? 如果实例显然是 ParentClass,仅此而已,为什么 ChildClass 不能访问其受保护的方法?或者有可能吗?


编辑:

看来,我的问题好像有误会。是的,我意识到无法访问 ParentClass 实例。但是,我担心这背后的原因是什么,以便我可以理解为什么

我的上述事后思考是否正确?我理解正确吗?

谢谢。

正如你所说。 parentInstance 可能ChildClass2 的一个实例,因此将该对象的受保护成员暴露给您的 ChildClass 可能会造成安全威胁。

想象一下以下场景:
你有一个可扩展的 class A,它将一些受保护的成员暴露给它派生的 classes(例如,它可能会改变受保护的状态或调用其他可能的虚拟成员)和一个派生的class B,它使用基本功能来做一些安全关键的事情,同时只公开一个安全的 API 进行各种错误和权限检查。

现在,您真的希望任何人都能够通过简单地从 A 派生 class C 轻松绕过这些检查,然后可以直接调用受保护的方法B?

类型的对象

"A protected member of a base class is accessible in a derived class only if the access occurs through the derived class type."

"The type or member can only be accessed by code in the same class or struct, or in a derived class."

在你的代码行中:

parentInstance.ProtectedMethod("A different child's protected method.");

'parentInstance' 不是 'ParentClass' 派生出来的,它 一个 'ParentClass'.

在你的另一行代码中:

((ChildClass)parentInstance).ProtectedMethod("A different child's protected method.");

您只是 告诉 编译器应该将 ParentClass 对象视为 ChildClass - 并且 ChildClass 可以访问它继承自的 class 的受保护成员.

但是,最终,代码将在 运行 时失败,因为 ParentClass 无法转换为 ChildClass。

这有点难以解释,所以如果这没有完全说明我会再试一次。 :)

(我看到你已经改变了你的问题,所以这可能不是你想要的。呵呵。)