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

时间:2017-07-11 03:50:04

标签: c# .net oop access-modifiers

我不明白为什么这段代码会给我一个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的受保护成员?

如何修改代码以使用HtmlNode 类型的限定符”,如错误消息中所示?

2 个答案:

答案 0 :(得分:9)

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

根据MSDN,protected关键字表示以下内容:

  

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

现在,让我们想象编译器让你编译它,现在你正在迭代你的集合并调用.ToText()方法。

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

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

public class AnotherNode : Node
{
    protected override string ToText()
    {
    }  
}

在这种情况下,您尝试调用ToText类的受保护AnotherNode方法 你是一个&#34;包含类(AnotherNode)&#34;?第
你是来自AnotherNode&#34;的#34;类型吗?第
因此,看起来您应该无法访问此方法。

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

答案 1 :(得分:1)

您需要在派生类中为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调用ToText() NodeB方法是否有意义?不,不是因为HtmlNode没有继承NodeB所以为什么要允许它访问protected的{​​{1}}方法?