所以我刚刚发现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
的后代。如果有一个班级,比如说ChildClass2 : ParentClass
,那么从ChildClass
开始访问受保护的成员是不正确的,因为ChildClass
并非来自ChildClass2
。转换为ChildClass
会告诉编译器您希望parentInstance
是ChildClass
个实例,而不是ParentClass
的其他后代。
然而,我看到另一个问题。 假设我将变量设置为:
c.ParentInstance = new ParentClass();
在这种情况下,ChildClass
无法访问受保护的方法(甚至不能使用强制转换,因为它无法转换为包含受保护方法的任何其他内容)。为什么会这样?
如果该实例显然是ParentClass
而且仅此而已,为什么ChildClass
无法访问其受保护的方法?或者有可能吗?
<小时/>
显然,似乎对我所要求的内容存在误解。是的我意识到无法访问ParentClass
实例。但是,我担心这背后的原因是什么,以便我能理解为什么。
我的上述事后才是否正确?我理解这个吗?
感谢。
答案 0 :(得分:1)
完全如你所说。 parentInstance
可能是ChildClass2
的实例,因此将该对象的受保护成员暴露给您的ChildClass会产生可能的安全威胁。
想象一下以下情况:
您有一个可扩展的类A
,它将一些受保护的成员公开给它的派生类(例如,可能改变受保护状态或调用其他可能的虚拟成员)和派生类B
,它们使用执行一些安全关键功能的基本功能,同时只暴露一个带有各种错误和权限检查的安全API。
现在,您真的希望任何人能够轻松绕过这些检查,只需从C
派生一个类A
,然后就可以直接调用{{1}类型的对象上的受保护方法}}?
答案 1 :(得分:1)
&#34;如果通过派生类类型进行访问,则只能在派生类中访问基类的受保护成员。&#34; < / p>
&#34;类型或成员只能通过在相同的类或结构中访问,或在的派生类中访问。&#34 ;
在您的代码行中:
parentInstance.ProtectedMethod("A different child's protected method.");
&#39;父辈&#39;不是来自&#39; ParentClass&#39; &#39; ParentClass&#39;。
在您的其他代码行中:
((ChildClass)parentInstance).ProtectedMethod("A different child's protected method.");
您只需告诉编译器将ParentClass对象视为ChildClass - 而ChildClass可以访问它继承的类的受保护成员。
但是,最终,代码将在运行时失败,因为ParentClass无法强制转换为ChildClass。
这有点难以解释,所以如果这没有完全合理,我会再试一次。 :)
(我看到你改变了你的问题,所以这可能不是你想要的。哼哼。)