当前位置:  开发笔记 > 编程语言 > 正文

为什么我不能访问C#受保护的成员,除非像这样?

如何解决《为什么我不能访问C#受保护的成员,除非像这样?》经验,为你挑选了3个好方法。

这段代码:

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);
    }
}

生成此错误:

无法通过类型为"C"的限定符访问受保护的成员'CF(D)'; 限定符必须是'D'类型(或从中派生)

他们在想什么?(会改变那条规则会破坏某些东西吗?)除了让F公开之外,还有其他方法吗?


编辑:我现在明白为什么会这样(感谢格雷格),但我仍然对理性感到有些困惑; 给定:

class E : C
{
    protected override void F(D d) { }
}  

为什么不应该 D是能够能够调用EF?


编辑错误消息,所以我可能会在那里输入错误.



1> Greg Beech..:

这不起作用的原因是因为C#不允许跨层次调用受保护的方法.假设有一个类E也来自C:

  C
 / \
D   E

然后,您尝试调用方法的引用实际上可能是类型的实例,E因此该方法可以在运行时解析E.F.这在C#中是不允许的,因为D无法调用E受保护的方法,因为E它位于层次结构的另一个分支中,即

var d = new D();
var e = new E();
d.G(e); // oops, now this will call E.F which isn't allowed from D

这是有道理的,因为关键字protected意味着成员" 可以在其类和派生类实例中访问 ",而EF不是D的成员.


这是一个有趣的观点.我一直认为DF和EF是CF的特殊情况,因此可以全部或全部方式访问.

2> JaredPar..:

"protected"关键字意味着只有从该类型派生的类型和类型才能访问该成员.D与C无关,因此无法访问该成员.

如果您希望能够访问该成员,则有几个选项

把它公之于众

把它做成内部的.这将允许任何类型访问同一程序集中的成员(或者如果你添加朋友的话,可以访问其他程序集)

从C中导出D.

编辑

这种情况在C#规范的第3.5.3节中提到.

不允许这样做的原因是因为它允许跨层次调用.想象一下,除了D之外,还有另一个基类C称为E.如果您的代码可以编译它将允许D访问成员EF这种类型的场景不允许在C#中(我相信 CLR但我不知道t 100%知道).

EDIT2为什么这很糟糕

警告,这是我的看法

现在允许这样做的原因是它很难推断出一个类的行为.访问修饰符的目标是让开发人员准确控制谁可以访问特定方法.想象一下下面的课程

sealed class MyClass : C {
  override F(D d) { ... } 
}

考虑如果F是一个有时间关键的功能会发生什么.根据目前的行为,我可以推断出我班级的正确性.毕竟只有两种情况会调用MyClass.F.

    它在C中被调用的地方

    我在MyClass中显式调用它的位置

我可以检查这些调用,并得出关于MyClass如何运作的合理结论.

现在,如果C#允许跨层次保护访问,我就不能做出这样的保证.任何完全不同的程序集中的任何人都可以来自C.然后他们可以随意调用MyClass.F. 这使我完全无法推断出我班级的正确性.


"D与C无关","如果你想能够访问该成员......从C中导出D".但在OP的帖子中:"D级:C级".
对于为什么继承的类在任何需要时都不能调用基类型的成员的解释,这些解释都没有使它更清楚。这就是“受保护”的重点。您无需为派生类公开某些内容即可访问它。如果D不是从C派生的,那就没有问题了。我不理解为什么基于OP示例以外的其他原因会接受此答案。

3> MSN..:

即使D继承自C,D也无法访问C的受保护成员.D可以访问D的受保护(和私有!)成员,所以如果你把D的另一个实例放在那里而不是C,一切都会工作.但随着格雷格说,C真会是完全不同的东西,因为编译器不知道什么C真的是,它具有防止d访问的东西d实际上可能没有能够访问.

一系列帖子从C#编译器的角度解释了这一点:

为什么我无法从派生类访问受保护的成员

为什么我无法从派生类访问受保护的成员,第二部分:为什么我可以?

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有