3

I was just tying to understand what is happening when I write a=c; when I checked type of "a" it is showing up as class "C". Now my question here is if "a" is pointing to "c" then why it is not behaving like pointer "c".

 class Program
    {
        static void Main(string[] args)
        {
            C c = new C();
            A a = new A();
            Console.WriteLine(a.GetType());
            a = c;
            Console.WriteLine(a.GetType());
            a.Show();
            c.Show();
            Console.ReadLine();
        }
    }
class A
{
    public virtual void Show()
    {
        Console.WriteLine("A.Show()");
    }
}

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

class C : B
{
    public new void Show()
    {
        Console.WriteLine("C.Show()");
    }
}

Output:

Output

Community
  • 1
  • 1
Saurabh Saxena
  • 117
  • 1
  • 11
  • 1
    "why it is not behaving like pointer "c"." What do you mean by this? – MakePeaceGreatAgain Apr 08 '18 at 12:49
  • 1
    I mean, Why is it calling "Show()" of Class B. – Saurabh Saxena Apr 08 '18 at 12:52
  • 1
    You used the `new` keyword to suppress a compiler warning. Which roughly says "are you sure you want to do this, it is probably wrong". Turns out that you were not sure. Change the name of C.Show to, say, ShowAlso() and you no longer need the new keyword. And what happens now when you run the program entirely makes sense. – Hans Passant Apr 08 '18 at 13:16

5 Answers5

4

It's because you're using the new keyword.

The new keyword simply hides the underlying method and replaces it with a new method. When you cast the object to A (or even B), you're using the hidden method in B, not the new method in C.

You can read more about it in the docs here and here.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • I know new keyword hides the underlying method however I am more interested in when I assign "**c**" class pointer to "**a**" and then check the type of **a** using **a.GetType()**, it is referencing to class **C**. Which means now **a** is pointing to the memory address of **C**. So why it didn't behave like pointer **c** as now "**a**" and "**c**" both are same. – Saurabh Saxena Apr 08 '18 at 13:21
  • 1
    @SaurabhSaxena Because C doesn't implement an override of your `Show` method. The last override for that method is `B`. By casting an instance of `C` to an `A` variable, you're instructing C# to use the most high level (`B`) override of the method from `A`. – ProgrammingLlama Apr 08 '18 at 13:26
3

Actually, it is 'a pointer "c"'. But as @John said, the new keyword is the issue here.

The result would be what you expected for if you didn't set a type to a variable.

For example:

public static void Main()
{
    C c = new C();
    object a = c;
    Console.WriteLine(a.GetType()); // It still is of `C` type instead of object as you've set
    ((A)a).Show(); // Prints out "C.Show" 
    c.Show(); // Prints out "C.Show"
    Console.ReadLine();
}

Once you're expecting an 'A' kind of behavior to the Show method it acts as an A known method. As C have a NEW behavior it's unknown to A (or B), even having an old Show (that's the inherited from B) for ascendents compatibility.

In resume: The Show method of C class is a new one that 'coincidentally' have the same name. But it's known by the C class (and it's children) only.

Diego Rafael Souza
  • 5,241
  • 3
  • 23
  • 62
  • 1
    `var a = c` is basically `C a = c`, so obviously it will print `C.Show`. `a` is of type `C`. If you write `A a = c`, it will print `B.Show` – w.b Apr 08 '18 at 13:19
  • @w.b _we have a badass over here_! It does not seem too obvious to the user that asked. He based his example in multiples references to the 'same memory pointer' in an inheritance context that he didn't understand very well, I'm trying to make it clear enough to him. If you don't like my answer, downvote me, no hard feelings =) – Diego Rafael Souza Apr 08 '18 at 13:27
  • Ok, no problem for me, just wanted to say you wrote the same thing twice, both `c` and `a` are of type `C`. – w.b Apr 08 '18 at 13:29
  • @w.b I was just reviewing this post, and you're right. I'm being redundant and repeating myself. I didn't choose a good code to exemplify what I would like. I'm trying to save it now. Thanks for notice and advice me =) – Diego Rafael Souza May 02 '18 at 16:55
  • I hope it be better now – Diego Rafael Souza May 02 '18 at 16:57
1

Because Show() method in C is not overridden. So when you assign c with a, it has not the behavior of the c but has the behavior of B. If you want a has c like show behavior you must override Show() method.

using System;

public class Program
{
    public static void Main()
    {
        C c = new C();
        A a = new A();
        Console.WriteLine(a.GetType());
        a = c;
        Console.WriteLine(a.GetType());
        a.Show();
        c.Show();
        Console.ReadLine();
    }
}

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

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

class C : B
{
    public override void Show()
    {
        Console.WriteLine("C.Show()");
    }
}
Milad Dastan Zand
  • 1,062
  • 1
  • 10
  • 21
1

Why is it calling "Show()" of Class B

Because a.Show() is virtual, the compiler seeks for the most overridden version in the hierarchy unless the overridden version has the new keyword, in which case the method implementation is hidden higher up in the class hierarchy. In your case the variable a points to an object of type C, but the C class hides Show, so the most derived version visible to compiler is B.Show().

w.b
  • 11,026
  • 5
  • 30
  • 49
0

If you wish to see C.Show() in the third line you need to change the function signature in class C to

public override void Show()

The "new" keyword is used to hide a method, property or event of the base class into the derived class.

When you write a=c; you downcasted a to c, so within runtime, the closest function to c in hierarchy will run.

petezurich
  • 9,280
  • 9
  • 43
  • 57
Dor Lugasi
  • 11
  • 2