【问题标题】:Why does this code results in Stack Overflow c#?为什么这段代码会导致 Stack Overflow c#?
【发布时间】:2019-12-01 20:58:55
【问题描述】:

下面的代码会引发堆栈溢出。 B 中的 DoSomething 调用 A 中的 DoSomething。A 中的 DoSomething 应该调用其 X 的方法实现,但它调用其派生类 B 的 DoSomething。为什么?这是一个错误吗?

namespace Test
{
    class Program
    {
        static void Main()
        {
            B b = new B();
            b.DoSomething();
        }
    }
    interface X
    {
        void DoSomething();
    }
    class A : X
    {
        protected void DoSomething() => ((X)this).DoSomething(); // Making visible to derived classes
        void X.DoSomething() => Console.ReadKey();
    }
    interface Y : X
    {
        void DoSomethingElse();
    }
    class B : A, Y
    {
        public new void DoSomething() => base.DoSomething(); //Making publically visible
        public void DoSomethingElse() { }
    }
}

顺便说一句,这段代码可以正常工作(如果我没有在 Y 中继承 X):

namespace Test
{
    class Program
    {
        static void Main()
        {
            B b = new B();
            b.DoSomething();
        }
    }
    interface X
    {
        void DoSomething();
    }
    class A : X
    {
        protected void DoSomething() => ((X)this).DoSomething(); // Making visible to derived classes
        void X.DoSomething() => Console.ReadKey();
    }
    interface Y
    {
        void DoSomethingElse();
    }
    class B : A, Y
    {
        public new void DoSomething() => base.DoSomething(); //Making publically visible
        public void DoSomethingElse() { }
    }
}

为什么在第一个例子中,B 中的 DoSomething 试图实现 A 已经实现的 X 的 DoSomething 方法。如果它没有错误,我如何在不修改 Y 接口的情况下阻止 B 类这样做。因为我想在 Y 中反映它继承了 X。

【问题讨论】:

  • StackOverflow 错误参考调用堆栈。基本上你的代码中有递归。并且 hte recurions 要么是无限的,要么是如此接近以至于绊倒了无限检测。但我不知道它在哪里,因为你把很多代码和继承扔到了我们的脸上。请为此问题提供一个最小示例。
  • Interfacs 的命名约定也是在其名称前面附加一个 i。这样我们就可以一眼看出class B : A, iY 不是 完全无效的多重继承尝试。而不必弄清楚您的自定义命名方案。

标签: c# inheritance interface


【解决方案1】:

它发生了,因为你的调用相互调用,这个public new void DoSomething() => base.DoSomething();正在调用基本方法,即protected void DoSomething() => ((X)this).DoSomething();

this 实例被强制转换为X 类型,这是由AB 实现的,显然((X)this).DoSomething();B 类调用DoSomething(),您将获得无限递归。

这种行为的原因是,当一个接口在类型层次结构中多次显式实现时,将使用最派生类型中的实现。详情可以关注language specification

您可以通过在类A 中创建DoSomething() 方法public 并删除它在B 中的声明来避免它,就像那样

class A : X
{
    public void DoSomething() => ((X)this).DoSomething(); // Making visible to derived classes
    void X.DoSomething() => Console.ReadKey();
}
interface Y : X
{
    void DoSomethingElse();
}
class B : A, Y
{
    public void DoSomethingElse() { }
}

【讨论】:

  • 我将其转换为 X。X 的 DoSomething 在 A 中实现,为什么它调用 B 的 DoSomething?
  • @ZDSAlpha 因为那是this.DoSomething() 所做的。
  • 如何让它调用在 A 中实现的 X.DoSomething?
  • 你已经找到解决办法了,去掉Y接口中的X继承
  • 我可以在不更改方法名称的情况下阻止 B 实现方法 X.DoSomething 吗??
猜你喜欢
  • 1970-01-01
  • 2011-03-16
  • 2012-08-27
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 2013-01-18
相关资源
最近更新 更多