1

Regarding this this post, it seem not to be possible to cast an derived class to it´s base class by the keyword as.

In the code of that post is used the keyword override. But when I use instead the keyword new, then the cast to the base-class becomes visible:

// base class
public class Aircraft
{
    public virtual void fly()
    {
        Console.WriteLine("Aircraft flies");
    }
}

// derived class
public class Plane : Aircraft
{
    public new void fly()
    {
        Console.WriteLine("Plane flies");
    }
}

public class Program
{
    public static void Main()
    {
        var plane = new Plane();
        Console.WriteLine(plane.GetType()); // "Plane"
        plane.fly(); // "Plane flies"
    
        var aircraft = plane as Aircraft; // <-- cast to base class
        Console.WriteLine(aircraft.GetType()); // "Plane"
        aircraft.fly(); // "Aircraft flies"
    }
}

The code aircraft.GetType(); indicates that the cast to the base class didn´t happen. It´s still a Plane. But aircraft.fly(); says, that the cast to the base class worked, because the method says: "Aircraft flies".

Who can solve my confusion?

Simon
  • 4,157
  • 2
  • 46
  • 87
  • 6
    `Regarding Jon Skeets answer in this post, it is not possible to cast an derived class to it´s base class by the keyword as` - Jon Skeet said no such thing. He said that you cannot cast an object in such way that you get to call the overridden methods of its base class. Otherwise you absolutely can cast an object to its base class, with `as` or otherwise. Here you don't have an overridden method, you have a shadowed method. Replace the `new` with `override`, and the plane will fly in both cases. – GSerg Jan 01 '23 at 10:18
  • 3
    Indeed. I'd appreciate it if you'd remove that first sentence so as not to misrepresent what I've said. – Jon Skeet Jan 01 '23 at 10:24
  • I have removed the relation to Jon Skeet. – Simon Jan 01 '23 at 14:32
  • Think about it. If the cast actually happen, how would the base class method ever be invoked? There would be no way to do it! – Mayur Ekbote Jan 01 '23 at 15:36

1 Answers1

3

You have an object created here:

new Plane();

It will always be of type Plane and this type cannot be changed (it would be another object then). Cast does not "change type" of object.

Now you have two variables pointing to this object. First variable plane is of type Plane, and second variable aircraft is of type Aircfart.

Then, Plane class has two separate methods with the same signature - fly(). One is inherited from base Aircraft class and another is declared with new keyword. When you call plane.fly() - compiler has to choose from two methods and is chooses the one with new keyword (by design). When you call aircraft.fly() - compiler has only one method to consider - fly() defined in Aircraft.

If you would override fly method in Plane class instead of declaring a new method with the same signature - then only one fly() method would exist and called in both cases, with implementation of the Plane class.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • `Cast does not "change type" of object.`: That was my fail in my mindset which confused me. I thought, that the type of an object will be changed by the keyword 'as'. With your answer I think now (pictorially explained), that the keyword 'as' fetches only the inherited methods into `Plane`, dependent on the keyword `override` and `new`. Is that correct? – Simon Jan 02 '23 at 08:35
  • It's better to think like your two variables provide two different views on the same Plane object to compiler. With "plane" variable compiler sees two fly() methods and chooses one declared in Plane class, because it has new keyword. With "aircraft" variable compiler sees only one fly() method on Aircraft class l, and calls that. This method is not overrided in Plane so Aircraft implementation is used. – Evk Jan 02 '23 at 10:28