无法访问派生类中的受保护方法

Posted

技术标签:

【中文标题】无法访问派生类中的受保护方法【英文标题】:Unable to access protected method in derived class 【发布时间】:2017-12-14 22:55:17 【问题描述】:

我不明白为什么这段代码会给我一个 Intellisense 错误。

public abstract class Node

    protected abstract string ToText();


public class htmlNode : Node

    public List<Node> ChildNodes  get; set; 

    protected override string ToText()
    
        StringBuilder builder = new StringBuilder();

        foreach (var node in ChildNodes)
            builder.Append(node.ToText());  // <=== THIS IS THE ERROR

        return builder.ToString();
    

在上面指出的那一行,我得到了错误:

错误 CS1540:无法通过“Node”类型的限定符访问受保护的成员“Node.ToText()”;限定符必须是“HtmlNode”类型(或派生自它)

HtmlNode 派生自Node,那么为什么HtmlNode 不能访问Node 的受保护成员?

我将如何修改代码以使用 "a qualifier of type HtmlNode",如错误消息中所建议的那样?

【问题讨论】:

问题是子节点列表是抽象节点的列表。那没有意义。抽象 Node 类必须像在 HTMLNODE 类中那样实现。要查看它的工作情况,请将子节点更改为 List... @JohnPeters:我正在使用抽象,所以我认为它非常有意义。我可以有几个Node 的子类,并且应该能够访问所有这些子类都通用的方法。您的解决方法仅适用于 HtmlNode 类型的节点。这不是我需要的。 @AzarShaikh 如果node 不是HtmlNode,那么它将崩溃。 我在这里发现了类似的问题:***.com/questions/13683324/… @JohnPeters:但是HtmlNode 实现抽象的类。为什么派生类不能访问基类的受保护成员? 【参考方案1】:

在我看来,您可以通过继承机制访问受保护的成员,但您仍然不能通过实例访问受保护的成员。

根据 MSDN,protected 关键字的含义如下:

protected - 访问仅限于包含类从包含类派生的类型

现在,让我们假设编译器允许您编译它,现在您正在遍历您的集合并调用 .ToText() 方法。

如果nodeHtmlNode 或其子类,那么您可以调用此方法。

但是,如果node 是某种类型的AnotherNode

public class AnotherNode : Node

    protected override string ToText()
    
      

在这种情况下,您正在尝试调用 AnotherNode 类的 protected ToText 方法。 你是“包含类(AnotherNode)”吗?没有。 你是“从另一个节点派生的类型”吗?没有。 因此,您似乎无法访问此方法。

由于ChildNodes 是编译时未知类型的实例,编译器无法确定您是否应该有权访问其方法。 这就是我看到编译器抛出这个异常的原因。

【讨论】:

我想这就是答案。当我用 C++ 编程时,我记得这非常好。如果它在 C# 中被允许,那将会很有用。【参考方案2】:

您需要在派生类中为ToText() 方法提供实现,但您在实现中调用基类ToText() 方法,这没有意义。想象一下,你试过了,这也行不通:

public class HtmlNode : Node

    protected override string ToText()
    
        base.ToText(); // Will not compile: Cannot call abstract base member
    

如果您使用HtmlNode 类,事情会变得更加清晰。所以让我们使用它:

HtmlNode node = new HtmlNode();
node.ChildNodes.Add(new HtmlNode());
node.ChildNodes.Add(new NodeB()); // Say NodeB inherits Node

HtmlNode 调用NodeBToText() 方法有意义吗?不,不是因为HtmlNode 没有继承NodeB 那么为什么要允许它访问NodeBprotected 方法?

【讨论】:

这就是虚函数的用途。这很有意义。 @JonathanWood 但它不是虚拟的。它是抽象的。在 C# 中,它们的处理方式不同。 抽象方法是自动虚拟的。否则,就没有办法实现它们。 @JonathanWood 很公平,是的,你说得对,抽象方法是虚拟的。但是必须实现抽象方法,并且在实现它们时,不能调用它。这没有任何意义。 @JonathanWood CodingYoshi 写道:“base.ToText(); // 不会编译:无法调用抽象基成员”——这是一个完全不同的问题,编译时 i> 对未定义函数的引用。继承方式不一样。编译器可以接受 OP 的代码,它会运行和工作正常,但这是一个权限问题,正如 Yeldar Kurmangaliyev 和 Eric Lippert 在 ashin 的已删除(不知道为什么)答案中的链接中所解释的那样:blogs.msdn.microsoft.com/ericlippert/2010/01/14/…

以上是关于无法访问派生类中的受保护方法的主要内容,如果未能解决你的问题,请参考以下文章

在派生类中无法访问受保护的成员

派生类无法访问基类的受保护方法

为啥我不能访问静态多态派生类中的受保护成员?

访问派生类中的受保护成员

Java中的间接子类无法访问的超类中的受保护成员

C#访问派生类中的受保护成员[重复]