收录日期:2019/05/22 09:17:58 时间:2009-06-18 11:26:33 标签:c#,oop

I have 2 classes Test(Base)and Program(child). Now I am facing some problem while downcasting.

        Test t = new Program();// upcasting-works
        Program p = (Program)t;//Downcasting-works
        Program q = (Program)new Test();//Downcasting -throws exception.

I want to know why its throwing exception? May b its very basic, but somehow I am not getting. Is it for that new object?

Thanks.

This is expected behaviour in all OO systems. In short, you cannot downcast to something for which the dynamic type is not matched. In this line:

Program q = (Program)new Test();

You are creating a Test instance - the instance obviously does not match Program since Test does not derive from Program. At runtime, the computer detects this is the case and throws the exception.

On the other hand, you have:

 Test t = new Program();

Here, you are creating a Program instance - the instance matches Test since Program does derive from Test.

Finally, and out of order, you have:

Program p = (Program)t;

In this case, t is a reference to Test, but the underlying type is really Program - at runtime, the computer is able to determine this is the case so the cast is allowed to work.

Every Square is a Rectangle but not vice versa. Similarly, every instance of a derived class is a valid instance of the base class but not vice versa. In your example, every Program is a Test but not all Tests are Programs.

The problem is: a Test instance isn't a Program. It works in the first case because the instance is created as a Program (on the first line).

With casts, the type of the actual object (not just the variable) is important.

Mehrdad has given the correct answer. Just to make it clearer:

Your Test is not a Program – the opposite is true: Program is-a Test in your case. Therefore, what you're trying to do isn't an upcast and it's not allowed.

Think of it like this, you can cast Program to Test, because Program IS A Test.

You cannot cast Test to Program, because Test is not a Program.

It is ALWAY safe to downcast, to it only safe to upcast when you are sure the object IS of that type.

Needing to upcast is often a code smell, if you find you often need to upcast your objects, there's probably something wrong with your design.

Hope this helps,

EDIT: Is it always safe to downcast?

The act of downcasting is by definition - according to me - where you know the type of the object, and you're casting it lower down it's inheritance tree. e.g. Cat and Dog both inherit from Animal, Oak and Birch both inherit from Tree.

it is ALWAYS safe to do this

public void DoThingWithCat(Cat snuggles)
{
    snuggles.Meow();
    DoThingWithAnimal(snuggles); // this is always OK, because we know 
                                 // the type of snuggles, and we know 
                                 // snuggles is an animal
}

This is an UpCast. It is not safe to do this, also this is a code is a code smell, there is probably something wrong with your object hierarchy if you need to do this.

public void DoSomethingElse(Animal anAnimal)
{
    DoThingWithCat(anAnimal);    // this is NOT always OK, because we
                                 // DO NOT know the type of anAnimal, 
                                 // and it may not be a Cat
}

This is also unsafe, because it's straight casting, not necessarily up casting or down casting

public void DoSomethingDifferent(object anObject)
{
    DoThingWithAnimal(anObject); // this may or may not work, 
                                 // depending on the type passed in, 
                                 // this is a recipe for disaster, 
                                 // because may not be an Animal, 
                                 // it could be a Tree.
}