Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 未调用具有多级继承的base.Method()?_C#_.net_Inheritance_Base Class - Fatal编程技术网

C# 未调用具有多级继承的base.Method()?

C# 未调用具有多级继承的base.Method()?,c#,.net,inheritance,base-class,C#,.net,Inheritance,Base Class,我一直在寻找,没有找到任何解决我问题的办法。我的情况非常简单: public class A { public virtual void MethodOne() { Console.log( "A" ); } } public class B : A { public override void MethodOne() { base.MethodOne(); Console.log( "B" );

我一直在寻找,没有找到任何解决我问题的办法。我的情况非常简单:

public class A
{
    public virtual void MethodOne()
    {
       Console.log( "A" ); 
    }
}

public class B : A
{
    public override void MethodOne()
    {
        base.MethodOne();
        Console.log( "B" );
    }
}

public class C : B
{
    public override void MethodOne()
    {
        base.MethodOne();
        Console.log( "C" );
    }
}
我试图做的是让C类的一个实例(我们将其命名为“instanceC”)调用其父类和其父类的重写方法。所以我希望:

instanceC.MethodOne();
// Output:
// "A"
// "B"
// "C"
但我得到的是:

instanceC.MethodOne();
// Output
// "A"
// "C"

跳过类B的方法。这不可能吗?我认为这就是遗传/多态性的全部要点。提前谢谢

您发布的示例非常有效,无论您在实际代码中做什么,都与您发布的不同

像你想的那样工作

using System;

public class Test
{
        public static void Main()
        {
                var c = new C();
                c.MethodOne();
        }
}

public class A
{
    public virtual void MethodOne()
    {
       Console.WriteLine( "A" ); 
    }
}

public class B : A
{
    public override void MethodOne()
    {
        base.MethodOne();
        Console.WriteLine( "B" );
    }
}

public class C : B
{
    public override void MethodOne()
    {
        base.MethodOne();
        Console.WriteLine( "C" );
    }
}

你的例子对我来说很有效。我看到了一个B C。我认为你最可能的问题是C没有扩展B。然而,在我们讨论这个问题时,让我提出一个可以说更安全的模式。您似乎希望MethodOne的所有重写都从它们的基类执行代码。很好,继承是一个很好的模式。但是,使用此模式,您无法强制继承器执行基本逻辑,因为您无法强制它们调用
base.MethodOne()
。即使它们调用了
base.MethodOne()
,也无法确保逻辑的顺序。他们会在方法的开头、中间还是结尾调用
base.MethodOne()
?通常,在这些类型的模式中,您希望子类在函数的开头执行所有基本逻辑。以下模式强制继承者按照基类期望的顺序执行基逻辑。从技术上讲,它不太灵活,但更安全,因为继承者必须以基类指定的方式扩展基类

public class A
{
    //Don't make this method virtual because you don't actually want inheritors 
    //to be able to override this functionality.  Instead, you want inheritors
    //to be able to append to this functionality.
    public void MethodOne()
    {
        Console.WriteLine( "A" ); 
        MethodToBeOverriddenOne();
    }
    //Expose a place where inheritors can add extra functionality
    protected virtual void MethodToBeOverriddenOne() { }      
}

public class B : A
{
    //Seal the method because you don't actually want inheritors 
    //to be able to override this functionality.  Instead, you want inheritors
    //to be able to append to this functionality.
    protected sealed override void MethodToBeOverriddenOne()
    {
        Console.WriteLine("B");
        MethodToBeOverriddenTwo();
    }
    //Expose a place where inheritors can add extra functionality
    protected virtual void MethodToBeOverriddenTwo() { }  
}

public class C : B
{
    protected sealed override void MethodToBeOverriddenTwo()
    {
        Console.WriteLine("C");
    }
}

你确定C来自B而不是A吗?为什么C来自B?您希望它继承自A。您的示例对我来说正如预期的那样工作,并打印“A B C”,同样对我来说,您的示例工作正常,您的原始文档中一定有缺失或错误code@Derek如果需要执行B的某些行为,但需要在调用之前或之后添加其他行为。有一次,由于XmlReader的原因,我不得不重写FileStream。我能够重写GetBytes,调用
base.GetBytes
从FileStream获取结果,将无效值更改为替换字符,然后将其传递给
XmlReader。Create
这是一个比另一个更好的答案,因为它清楚地显示了如何确保始终调用基本方法。不知道为什么被否决。我睡得很少,你们是对的;C愚蠢地扩展了A而不是C。所以,虽然这确实是个问题,但我确实认为这是一个更好的解决方案,而且我有很好的结果。非常感谢。不是我投了反对票,我认为这也比我的好,并给了它一个+1个我知道的老问题,但我只是想补充一点,如果这是你想要的,这显然是一个很好的模式。如果您需要客户机能够禁用基类功能(并实际覆盖它),那么这不是一条可行的道路。当然,您首先要调用
base.MethodOne()