无法从派生 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()
函数中,我希望我可以通过注释掉的代码访问受保护的成员。毕竟,编译器不应该拥有所有必要的信息来判断这是一个安全访问吗?它知道 parentInstance
是 ParentClass
类型,它知道 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。
这有点难以解释,所以如果这没有完全说明我会再试一次。 :)
(我看到你已经改变了你的问题,所以这可能不是你想要的。呵呵。)
所以我刚刚发现 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()
函数中,我希望我可以通过注释掉的代码访问受保护的成员。毕竟,编译器不应该拥有所有必要的信息来判断这是一个安全访问吗?它知道 parentInstance
是 ParentClass
类型,它知道 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。
这有点难以解释,所以如果这没有完全说明我会再试一次。 :)
(我看到你已经改变了你的问题,所以这可能不是你想要的。呵呵。)