2

i have a base class and derived class like below

 public class BaseClass
{
    public int No { set; get; }
}

public class Derived : BaseClass
{
    public string Name { set; get; }
}

when i create instance of base class and want to downcast it to derived class it returns InvalidCastOperation.

class Program
{
    static void Main( string[] args )
    {
        BaseClass bas = new BaseClass();
        Derived derived = (Derived)bas; // invalid cast operation. why?
        System.Console.WriteLine();
    }
}

I am wondering why it does not work? and is a solution to implement this request?

4
  • Possible duplicate of stackoverflow.com/questions/1524197/downcast-and-upcast
    – Nibor
    Commented Feb 23, 2017 at 10:35
  • 1
    This should be called upcasting.
    – Sinatr
    Commented Feb 23, 2017 at 10:35
  • All Derived are BaseClass but not all BaseClass are Derived
    – Nkosi
    Commented Feb 23, 2017 at 10:36
  • You are initializing Base class and trying to cast it to derived class. Base class do not have any information about the derived class and it do not have properties related to derived class too. So it can't be done. Derived class can be casted to base class but vice a versa is not possible. It would be better if you explain what you are trying to achieve here.
    – Brijesh
    Commented Feb 23, 2017 at 10:40

8 Answers 8

9

It's because you need to create an instance of Derived if you want to be able to cast back to it:

BaseClass bas = new Derived();

then you will be able to cast the bas instance (which is declared as BaseClass type) to the concrete Derived class that it is an instance of:

Derived derived = (Derived)bas;
7

Use more meaningful names:

class Fruit { }
class Apple : Fruit { public int PitCount; }

Fruit f = new Fruit(); // f is just some undetermined Fruity thing
Apple a = (Apple) f;   // why would it be an Apple? Where would PitCount come from?

The way to prevent some of this kind of errors is to make Fruit abstract.
A more common usage pattern, when f can come from various sources, is:

if (f is Apple)
{
    Apple a = (Apple) f; // now it will work
}
1
  • 2
    nice example. thanks to other friends for their response
    – Xeta7
    Commented Feb 23, 2017 at 10:47
6

You created an instance of BaseClass and try to cast it to Derived. Of course it fails. Every Derived is also a BaseClass, but definitely not the other way around.

If you did

BaseClass bas = new Derived();
Derived derived = (Derived) bas;

it would work since the instance is actually an instance of Derived.

2

The rules for inheritance are:

  • Every instance of a derived class is also a instance of the base class
  • The other way around does not apply. Not each base class is also one specific derived class. It could be simply an instance of the base class (like in your example), or an instance of another class which is derived from Base.

To fix your example:

BaseClass bas = new Derived();
Derived derived = (Derived)bas; // or better: = bas as Dervied
4
  • Why should bas as Derived be better in your view? We allready know bas actually is an instance of Derived, no need for a safe-cast and checking for null. Commented Feb 23, 2017 at 10:51
  • In this situation yes - it doesn't matter. It's only that I would in general prefer a safe cast (and type check) instead of simply an exception getting thrown. Commented Feb 23, 2017 at 10:56
  • Type-checking and safe-casting is useless, you´re better better be off using as-cast and check for null or if you really want the type-check then use direct-cast afterwards. But this is out of the scope of the question or this answer, just an aside. Commented Feb 23, 2017 at 11:55
  • That's what I meant. An as cast plus null check is a form of a type check for me. The is operator is another - depends on the situation what is preferable. Commented Feb 23, 2017 at 11:58
1

You can't cast a base object to a derived type because the object is not of the derived type. The other way around works because a DerivedType object is also a BaseType by nature of inheritance. The reverse is not also true - a BaseType is not necessarily a DerivedType.

Think of it like this. You can do this:

Square a = new Square();
Shape b = (Shape)a;

because inheritance allows it to happen - a square is a shape.

However, trying to do this:

Shape a = new Shape();
Square b = (Square)a;

wouldn't work, because even though a square is a shape, the same can be said of a triangle, a circle, a parallelogram, or a trapezoid. It doesn't make sense to be able to take any random shape and say it can be any of those since that would be the same as saying that it is all of those, which is obviously not true - a square is not, and never will be, a triangle.

1

What do you expect when you write this:

object o = new object();
MyClass m = (MyClass) o;

Of course this fails as o is just an object without any knowledge on MyClass. In particular o doesn´t know how to set fields and properties defined in MyClass, so when creating o you can set just those members defined in object, not those for MyClass. Thus what would happen if the cast would succeed? You had an instance of object with just those members, cast it to MyClass and get an invalid instance of the latter as none of its members was initialized.

In other words: every instance of MyClass is an object, but of course not every object is a MyClass.

You have several opportunities.

  1. Create an instance of your derived class

    BaseClass b = new Derived();
    
  2. Create a copy-constructor that creates a new instance of Derived based on the current instance of BaseClass:

    public class BaseClass
    {
        public int MyProperty { get; set; }
    }
    
    public class Derived : BaseClass
    {
        public string AnotherProperty { get; set;}
    
        public Derived(BaseClass b)
        {
            this.MyProperty = b.MyProperty;
            this.AnotherProperty = "MyValue";
        }
    }
    
  3. Use some reflction-based code that creates a new instance of Derived and copies all properties and fields from an existing instance of BaseClass. This is quite similar to 2. but avoids that you have to set the members yourself in the code.

0

You Derived extends BaseClass.

You create Basclass with one attribute.

When you try casting it to Derived the attribute Name hasnt been created (so to speak)

If you were to try

 Derived derived = new Derived();
 BaseClass bas =(BaseClass)derived;
 System.Console.ReadLine();

it would work because derived extends base, so when derived is created it has both Name and No casting it to BaseClass effectively removes the Name variable.

Casting cannot add variables as you are trying to do. It expects it to be there, but its not.

0

To answer why this fails is basically because your Derived EXTENDS your BaseClass. Meaning that it adds more (functionality, fields ... ) to it which is not present into your BaseClass. For this to work compiler would have to magically create a new instance that contains this extensions and then assign it to your field/variable.

Clearing things up. Whenever you're creating an instance of an object it creates all of the members inside of that type ( with base type metadata included ). And since your BaseClass was created as that type it does not know anything about Derived. Not mentioning nothing about new property introduced by your Derived object.

// BaseClass :
//  - metadata of this type and System.Object ( because every object derives from System.Object in C# )
//  - field info of "No" property's backing field 
//  - property info "No" property

// Derived :
//  - metadata of this type and BaseClass type
//  - field info of "Name" property's backing field 
//  - property info "Name" property

Not the answer you're looking for? Browse other questions tagged or ask your own question.