Casting Issue Correct Question! Sorry

D

Daniel

Hi guys who just answered me.....it really would have helped if i had
written it right.

Ok i will use better names to explain my problem.

I have this:

InterFaceClass
^
ClassA
^
^
ClassB
ClassC


So i have an interface class that ClassA inherits from. ClassB and C then
inherit from classA.

i then want to do this:

ClassB myObj = (ClassB)some_ClassA_Instance;

And i get a invalid cast. Why?
 
C

Chris Dunaway

Daniel said:
Ok i will use better names to explain my problem.

I have this:

InterFaceClass
^
ClassA
^
^
ClassB
ClassC


So i have an interface class that ClassA inherits from. ClassB and C then
inherit from classA.

i then want to do this:

ClassB myObj = (ClassB)some_ClassA_Instance;

And i get a invalid cast. Why?

If we use different names, maybe it will be clearer:

interface IAnimal //Animal Interface
class AnimalBase : IAnimal //Animal base class

class Dog : AnimalBase //A Dog is an animal
class Cat : AnimalBase //A Cat in an animal

AnimalBase obj = new AnimalBase(); //This is a generic animal,
it could be anything

Dog myDog = (Dog)obj; //Try to cast generic animal to Dog
//This is not valid because an
animal may not be a dog

AnimalBase obj = new Dog(); //This is valid because a Dog *is* an
Animal
//However you can only
access the properties of a
//Generic animal

Dog myDog = (Dog)obj; //This is now valid because obj is
actually a Dog
Cat myCat = (Cat)obj; //This is *invalid* because obj is
*not* a Cat.

Hope this helps a little.

Chris
 
D

Daniel

Well in regrds to this.

The situation i have is that I want the class A object to have certain
methods overridden and its behaviour changed, class B and C.

So if i want ClasC implementation i cast it....(i now know i cant). So how
using that setup do i get that requirement?
 
D

Daniel

Can i ask then....

How would you then tell a generic animal object later that it is now a dog
object? You can't cast it so what do you do? Can this be done? i have a
sense a factory pattern solves my problem but i am not sure.
 
P

Peter Duniho

Daniel said:
Can i ask then....

How would you then tell a generic animal object later that it is now a dog
object?

If you initially created the object as a generic animal, you can't. The
type of an object cannot change during its lifetime. If it wasn't a Dog to
start with, it will never be a Dog.

If you like, you can create a Dog class that takes as a parameter to the
constructor an Animal instance, and then copies the information from that
Animal to a *new* Dog instance. That would allow you a way to create a
*new* Dog that inherits the generic characteristics of the Animal instance
you have (or the Animal-specific characteristics of any other Animal-derived
class, for that matter). But you cannot change a generic Animal instance
that isn't already a Dog into a Dog.

Pete
 
J

Jon Skeet [C# MVP]

Daniel said:
Basically you can cast up you cant cast down. I get it now.

You can cast down when the type of the actual object is compatible with
the type you're casting to, but you can't pretend that an object is of
a different type. So this is okay:

object o = "hello";
string x = (string) o;

but this isn't:

object o = new object();
string x = (string) o;
 
D

Daniel

Ok i understand now.

What i dont get is this.

GenericAnimal g = (GenericAnimal)Dog;

yet if you look at g's type it remains Dog?? Why has it not become a generic
type?
 
D

Daniel

Then i am confused again.

My class that was i was casting down to inherited and did not have any new
methods, just one inherited method that was overidden by implementation? Why
couldnt i cast?
 
P

Peter Duniho

Daniel said:
Then i am confused again.

My class that was i was casting down to inherited and did not have any new
methods, just one inherited method that was overidden by implementation?
Why couldnt i cast?

Did you read the other thread to which I pointed you? If you haven't, go
back and do that now. I don't know if it will answer your question, but if
you haven't tried, there's no point in anyone making a further effort to
help.

I don't think you understand the difference between the class itself and an
instance of that class. As I posted earlier, the question of whether an
inherited class has new methods, new fields, overridden methods, etc. is
entirely irrelevant to the question of casting. Once you create an instance
of a class, its type is determined. No amount of casting will change that.
If the instance was not originally created as the more-derived type, you
cannot later cast it to that more-derived type.

Pete
 
P

Peter Duniho

Daniel said:
Ok i understand now.

What i dont get is this.

GenericAnimal g = (GenericAnimal)Dog;

yet if you look at g's type it remains Dog?? Why has it not become a
generic type?

Did you read the other thread I pointed you to?

The instance doesn't change type. Only the type of the reference *to* that
instance has changed. Casting it to GenericAnimal doesn't change the
instance...it just restricts your view of the instance to those things
within a GenericAnimal.

Sometimes I wonder if teaching people OOP with C# is such a great idea.
Ironically, because things are more abstracted in comparison to C++, the
difference between an object and a reference to that object are lost. I
suspect that if people had to distinguish between an instance and a pointer
to that instance (as they do in C++), these questions wouldn't come up
nearly as often as they do.

Anyway, back to the question: "g" is not the instance. It's a reference to
the instance. Likewise, "Dog" is not the instance, it's a reference to the
instance (that is, let's ignore that you made the same error you made
previously, using the name of a class rather than the name of an instance of
that class :) ). The type of the reference affects what of the instance you
can look at, but it doesn't change the instance itself. When you create a
new Dog, you are creating an instance. The variables that reference that
instance define the type used to view the instance, but not the type of the
instance itself.

Thus, the instance always keeps its original type. You can always cast
references to that type back and forth, as long as they remain consistent
with the type of the actual instance. IMHO, it's a mistake to think of
casting as being "up-cast" or "down-cast". In all cases, the casting is
just providing a new type through which to view the instance. The type cast
to must always be a type within the inheritance tree of the instance, and
will always either be the type of the instance itself, or an ancestor of
that instance's type (that is, a base class). But no matter what happens,
the validity of the cast is relative to the original instance, not the type
being cast from.

Pete
 
T

Tom Porterfield

Daniel said:
Ok i understand now.

What i dont get is this.

GenericAnimal g = (GenericAnimal)Dog;

yet if you look at g's type it remains Dog?? Why has it not become a
generic type?

It is its generic, but it is also a Dog. So you could use g wherever a
GenericAnimal is called for and wherever a Dog is called for. But just
because you are treating it as a GenericAnimal doesn't mean it isn't still a
Dog. A Dog is a GenericAnimal, and this specific instance of a
GenericAnimal is a Dog, but not all GenericAnimals are Dogs.
 
J

Jon Skeet [C# MVP]

Daniel said:
Then i am confused again.

My class that was i was casting down to inherited and did not have any new
methods, just one inherited method that was overidden by implementation? Why
couldnt i cast?

Just because it doesn't have any new methods or fields doesn't mean you
can cast from one form to the other. It's not the right type, that's
all there is to it.
 
D

Daniel

Ok great

Thanks guys i fully understand now.

i am one of these people that doesn't like a 'vague' understanding, i keep
asking questions until i feel i understand 100% which i do now. I think it
is my c++ background haunting me and it has taken a while to adjust to the
no pointer scenario.

Thanks for all the replies and patience.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top