none
Why does this code results in Stack Overflow? RRS feed

  • Question

  • The code below throws stack overflow. DoSomething in B calls DoSomething in A. DoSomething in A is supposed to call its X's implementation of method but it calls DoSomething of its derived class B. Why? is this a bug?

    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() { }
        }
    }
    

    BTW this code works fine (if I do not inherit X in Y):

    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() { }
        }
    }
    


    Allow time to reverse.

    Sunday, December 1, 2019 8:50 PM

Answers

  • Or if you want Y to inherit X and resolve the exception, then you can make A's explicit implementation of X to call the protected DoSomething.

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

    • Marked as answer by Abdu Rahman Monday, December 2, 2019 9:17 AM
    Monday, December 2, 2019 5:49 AM

All replies

  • Greetings Abdu.

    In A's version of DoSomething, you are effectively doing this.

    B b = new B();
    X x = (X)b;
    x.DoSomething();

    That is, you are taking an object which was created as an instance of B, casting it to X, then calling DoSomething. It doesn't matter that this happens in A's code. The important thing is that the the compiler only knows it's an X after the cast, so it looks for the implementation of DoSomething in the object as it was created.

    If you change interface Y so that it no longer implements X, this means B does not implement X directly, but its base A does, so a call to X.DoSomething goes straight to A's implementation.

    Sunday, December 1, 2019 11:44 PM
  • Or if you want Y to inherit X and resolve the exception, then you can make A's explicit implementation of X to call the protected DoSomething.

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

    • Marked as answer by Abdu Rahman Monday, December 2, 2019 9:17 AM
    Monday, December 2, 2019 5:49 AM