这段代码:
abstract class C
{
protected abstract void F(D d);
}
class D : C
{
protected override void F(D d) { }
void G(C c)
{
c.F(this);
}
}
Run Code Online (Sandbox Code Playgroud)
生成此错误:
无法通过类型为"C"的限定符访问受保护的成员'CF(D)'; 限定符必须是'D'类型(或从中派生)
他们在想什么?(会改变那条规则会破坏某些东西吗?)除了让F公开之外,还有其他方法吗?
编辑:我现在明白为什么会这样(感谢格雷格),但我仍然对理性感到有些困惑; 给定:
class E : C
{
protected override void F(D d) { }
}
Run Code Online (Sandbox Code Playgroud)
为什么不应该 D是能够能够调用EF?
编辑错误消息,所以我可能会在那里输入错误.
我最近发现派生类中的方法只能通过派生类(或其子类之一)的实例访问基类的受保护实例成员:
class Base
{
protected virtual void Member() { }
}
class MyDerived : Base
{
// error CS1540
void Test(Base b) { b.Member(); }
// error CS1540
void Test(YourDerived yd) { yd.Member(); }
// OK
void Test(MyDerived md) { md.Member(); }
// OK
void Test(MySuperDerived msd) { msd.Member(); }
}
class MySuperDerived : MyDerived { }
class YourDerived : Base { }
Run Code Online (Sandbox Code Playgroud)
我设法通过向基类添加静态方法来解决此限制,因为允许Base的方法访问Base.Member,而MyDerived可以调用该静态方法.
不过,我仍然不明白这种限制的原因.我已经看到了几个不同的解释,但他们无法解释为什么仍然允许MyDerived.Test()访问MySuperDerived.Member.
Principled说明:'受保护'意味着它只能被该类及其子类访问.YourDerived 可以覆盖Member(),创建一个只能由YourDerived及其子类访问的新方法.MyDerived无法调用重写的yd.Member()因为它不是YourDerived的子类,并且它不能调用b.Member(),因为b实际上可能是YourDerived的一个实例.
好的,但是为什么MyDerived可以调用msd.Member()?MySuperDerived可以覆盖Member(),并且只有MySuperDerived及其子类才能访问该覆盖,对吧?
直到运行时才知道您是否正在调用被覆盖的成员.当成员是一个字段时,它无论如何都不能被覆盖,但仍然禁止访问.
实用主义解释:其他类可能会添加您的类不了解的不变量,您必须使用它们的公共接口,以便它们可以维护这些不变量.如果MyDerived可以直接访问YourDerived的受保护成员,它可能会破坏这些不变量.
我同样的反对意见适用于此.MyDerived不知道MySuperDerived可能添加的不变量 - 它可能由不同的作者在不同的程序集中定义 - 为什么MyDerived可以直接访问其受保护的成员?
我得到的印象是,这种编译时限制是作为一种错误的尝试来解决一个实际上只能在运行时解决的问题.但也许我错过了一些东西.有没有人有这将通过类型YourDerived或基地的变量让MyDerived访问基地的保护成员造成的,但问题的例子不是 …
我已经读过可以从派生类访问受保护的成员,但以下内容不起作用.
class A
{
protected int Test;
}
class B:A
{
A instanceOfA= new A()
public B()
{
instanceOfA.Test //Not possible
}
}
Run Code Online (Sandbox Code Playgroud)