-2

The following code gives different outputs. Can anyone explain why?

The code is displayed below. The result set is shown underneath it. I have compiled the code on Enterprise VS 2015, Update 2.
I run it on Win7.

Please notice that I am using shadowing (hiding) in both examples. This question doesn't concern the use of shadowing vs overriding. The question asks "Why does shadowing result in two different outputs?"

Here is the code that compiles and runs and gives different results for the two different methods of calling the objects:


using System;

namespace InheritanceApplication
{
    internal class FooBarParent
    {
        public void Display()
        {
            Console.WriteLine("FooBarParent::Display");
        }
    }

    internal class FooBarSon : FooBarParent
    {
        public new void Display()
        {
            Console.WriteLine("FooBarSon::Display");
        }
    }

    internal class FooBarDaughter : FooBarParent
    {
        public new void Display()
        {
            Console.WriteLine("FooBarDaughter::Display");
        }
    }

    internal class Example
    {
        public static void Main()
        {
            GoodBar();
            FooBar();
        }

        public static void GoodBar()
        {
            Console.WriteLine("Example::Goodbar ...");

            var fooBarParent = new FooBarParent();
            fooBarParent.Display();

            var fooBarSon = new FooBarSon();
            fooBarSon.Display();

            var fooBarDaughter = new FooBarDaughter();
            fooBarDaughter.Display();
        }

        public static void FooBar()
        {
            Console.WriteLine();
            Console.WriteLine("Example::Foobar ...");

            var fooBarFamily = new FooBarParent();
            fooBarFamily.Display();

            fooBarFamily = new FooBarSon();
            fooBarFamily.Display();

            fooBarFamily = new FooBarDaughter();
            fooBarFamily.Display();
        }
    }
}

Here is the result set:


Example::Goodbar ...
FooBarParent::Display
FooBarSon::Display
FooBarDaughter::Display

Example::Foobar ...
FooBarParent::Display
FooBarParent::Display
FooBarParent::Display
werp
  • 80
  • 8
  • 2
    Do you know what is `virtual` and when do you "_have_" to use it? And using `var` is ambigous – Khalil Khalaf May 31 '16 at 15:06
  • 2
    Take a look at this [SO Question](http://stackoverflow.com/questions/392721/difference-between-shadowing-and-overriding-in-c). – Alessandro D'Andria May 31 '16 at 15:06
  • in `FooBar`, `fooBarFamily` is *statically typed* as an instance of `FooBarParent`. So when you set it to and instance of `FooBarSon` that doesn't change. So it will still call `FooBarParent.Display()`. – Matt Burland May 31 '16 at 15:10
  • I would guess it has something to do with the time when it is determined what type fooBarFamily is. I Think it is determined during compile time so that should answer it... but during debugging it seems that the type is correctly assumed. – Bongo May 31 '16 at 15:14
  • 1
    I reject that this is a duplicate question to Ivan Stoev's Difference between shadowing and overriding in C#? 5 answers. – werp May 31 '16 at 15:20
  • 1
    Please note that I it would be best to use virtual. However, I am not asking "how best to write the code". I am asking, why does this code give different outputs? – werp May 31 '16 at 15:22
  • Ivan, please undo your Duplicate Code Marking or answer my question concerning the results. – werp May 31 '16 at 15:40
  • var fooBarFamily = new FooBarParent(); <-- Compiletime . In fact what you read here is FooBarParent fooBarFamily = new FooBarParent(); – Bongo May 31 '16 at 15:41
  • Question was answered on Microsoft's social media network: – werp May 31 '16 at 18:57
  • See https://social.msdn.microsoft.com/Forums/vstudio/en-US/ff15ba29-0b9d-4eb7-a696-b00d915fae66/two-similar-c-inheritance-implementations-give-vastly-different-results?forum=csharpgeneral – werp May 31 '16 at 18:57
  • @Servy, did you notice my comments to Ivan Stoev? This question has not been asked before. It is not a duplicate question. Please check the Microsoft social network site to find out why this is a unique question: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ff15ba29-0b9d-4eb7-a696-b00d915fae66/two-similar-c-inheritance-implementations-give-vastly-different-results?forum=csharpgeneral – werp Jun 07 '16 at 14:49
  • It answers your question; that makes it appropriate to close as a duplicate. Nothing in that link changes that. – Servy Jun 07 '16 at 14:52
  • @Servy, we can get into an argument offline. Your flag stops discussion on my question. My question asks why this is result happens, what is going on in the compiler to cause this problem. It turns out that it has to do with pointers in the compilation and that that phenomenon can be overridden with the "dynamic" prefix. That is what Microsoft points out. Yes "hiding" can fix it. But "dynamic" more strongly suggests what the compiler is doing. What you are doing is stopping discussion by placing the duplicate flag. – werp Jun 07 '16 at 15:04
  • This isn't a problem. This is just how non-virtual methods work. `dynamic` does nothing here, all your code shows is that the compile time type of an expression determines the implementation used when you have non-virtual methods, which the duplicate explains. – Servy Jun 07 '16 at 15:14
  • @Servy, you claim to understand the use of `dynamic`. Your understanding runs counter to the phenomenon that exhibits itself in the code above and the understanding that is explained on the Microsoft Social Network site. I have tried to explain these subtleties to you. But, you hold the power of the flags that you set on any question. Ivan Stoev unset that flag, but you chose to override what he reset. What you have done is stifle discussion. – werp Jun 07 '16 at 22:41
  • @werp I simply said that `dynamic` has nothing to do with the behavior describe in the question, which is true, because it has nothing to do with it. Your question is asking how non-virtual methods behave, that's it. The fact that you want people to post entirely offtopic answers, but you can't hope for that if the question is closed as a duplicate of a question that *actually answers your question* means that the closure is simply doing its job. You have the answer to your question, we don't *want* people posting random offtopic posts that have nothing to do with it. – Servy Jun 08 '16 at 01:11

2 Answers2

3

When you do this:

var fooBarFamily = new FooBarParent();

You're (implicitly) declaring fooBarFamily to be of type FooBarParent.

Because the Display method is not virtual, there is no virtual dispatch. So the method you call is determined only by the declared type of fooBarFamily.

Therefore, in every call to fooBarFamily.Display, you are calling FooBarParent.Display(), no matter what the runtime type of the instance is.

Contrariwise, when you give each instance its own var, the type is inferred to be the type of the instance you're creating:

var fooBarSon = new FooBarSon();

gives you a fooBarSon of type FooBarSon, and therefore you're calling FooBarSon.Display(); and similarly for fooBarDaughter.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
0

You should not use new in inheritance scenario public new void Display(). When you say new instead of override, you cancel inheritance for this method. To get right behavior you should write:

internal class FooBarParent
    {
        public virtual void Display()
        {
            Console.WriteLine("FooBarParent::Display");
        }
    }

    internal class FooBarSon : FooBarParent
    {
        public override void Display()
        {
            Console.WriteLine("FooBarSon::Display");
        }
    }

    internal class FooBarDaughter : FooBarParent
    {
        public override void Display()
        {
            Console.WriteLine("FooBarDaughter::Display");
        }
    }
Kirill Bestemyanov
  • 11,946
  • 2
  • 24
  • 38
  • Msdn Says: "The override modifier extends the base class method, and the new modifier hides it" (https://msdn.microsoft.com/en-gb/library/ms173153.aspx). Why shouldn't he use new if he wants to hide the original ? – Bongo May 31 '16 at 15:19
  • I recognize that there are better ways of writing the above code. I am not asking "how do I get the results I am looking for". I am asking "why do I get two different results?" – werp May 31 '16 at 15:29