Downcasting safety

1.2k views Asked by At

Here's the code:

Base b = new Derived(); // Upcasting
// Some actions
Derived d = (Derived)b; // Downcasting 

As I understand the reference is like stencil through which you're looking at some chunk of memory. And upcasting just narrows that stencil so you cannot access the members added with Derived class. And Downcasting here is expanding that stencil back again.

The question is: Since no reference to derived part of type preserved, just the Base. Can it happen that some actions or activity of GC will erase or overwrite the chunk of memory that used to contain Derived members by the time the downcasting occured? In other words can downcasting Derived d = (Derived)b fail?

4

There are 4 answers

0
Dmitry Bychenko On BEST ANSWER

That's a safe cast in the context. You've created Derived instance that's why it's always safe to treat Derived as Derived; no GC activity can spoil a part of the instance. Casting is a kind of treatment (I'm going to treat actual Derived istance as being Base only: I've promised to call just a subset of methods, properties) and casting to itself is always safe.

  // Actual instance is derived, but I'm going to restrict 
  // my work with them: I've promissed not to call for "b"
  // any derived methods/properties  
  Base b = new Derived(); 

  // What is the actual type of "b"?
  String typeName = b.GetType().Name; // <- "Derived"

  // Try to convert to Derived 
  // This's better way to cast then (Derived) b
  Derived d = b as Derived;

  // Since "b" is actually Derived d will ne not null
  if (Object.RefrenceEquals(null, d)) {
    Console.Write("b is Derived");
  }

  // You can also check
  if (b is Derived) {
    Console.Write("b is a Derived instance.");
  }
0
Matten On

The variable points to a memory location where the actual object resides. If you created an object of type Derived, the variable points to the memory location where the instance of this type is located at. Even if you're using the base type Base, the instance in memory is of the type you instanciated. So the downcast can't fail as long as you're sure b is of type Derived.

0
nvoigt On

No, it cannot lose information. However, the cast can fail if that information was never there in the first place. If b was never of type Derived or a derived type, it will throw an exception.

Base b = new b();
// Some actions
Derived d = (Derived)b; // will fail, b never was of type Derived.
2
Kelmen On

1) by the time "GC will erase ... the chunk of memory" that storing the b, your code "= (Derived)b" b is no longer in memory, of course it will failed, but GC shouldn't erase it, unless you playing around with weak-referencing.

2) Base b = new Derived(); I don't understand why you want to do this "upcasting". your code already has a strong reference/type of Derived, may as well use Derived b = ....