The post C# Introduction lists all of the C# series of posts we have at this site.
What is upcasting and downcasting? Upcasting is conversion from a derived (child) class to a base (parent) class. It’s like going up the family tree. Downcasting is the opposite: going from a base class to a derived class, down the tree. We will also look at the as and is keywords.
Upcasting
Let’s say we have a class called Shape and a class called Circle. Shape is the parent and circle is the child. Below is some code you could try for yourself. An object reference can be implicitly converted to a base class reference. Below we convert a circle reference to a shape reference (base class/parent class).
Shape shape = text; // upcasting - implicit conversion here
26
// text and shape are both references to the same object in memory.
27
// shape does not have access to FontSize or FontName, soo
28
// what's the point of limiting yourself?
29
}
30
}
31
}
Both text and sharp in the above code are referencing the same object but they are not the same. They have different views of that object. Both can access and modify the Height and Width for example. Now here we are starting to hint at polymorphism. So the question is, when would I need to know how to do this? What’s a real-world example?
StreamReader
The StreamReader works with streams. A stream could be a file or a memory stream. If we have an object of type SteamReader we can see how this works. The Object Browser shows you that FileStream derives from Stream. MemoryStream derives from Stream. In the constructor of the StreamReader object we can pass any object who’s type derives from the Stream class. Therefore we can pass a new FileStream or a new MemoryStream. Let’s look at some code.
MemoryStream will be automatically upcast to Stream in the example above.
ArrayList
Consider another example. Normally we don’t use ArrayList as it is prone to errors made by programmers. A better way is to use a Generic list because with that we specify the type of objects that are inside the list. All of the objects in the Generic list will all be of the same type.
So what is the key take-away from this? In C# upcasting is implicit so we can convert an object’s reference to its base class reference. Wherever a method requires an object of a given type, you can pass an object of that type or of any of the types that derive from that type.
Downcasting
Here is an example of downcasting. We have a shape called shape and we are going to assign it to a Text. At compile time it is a shape but at run time it will be Text. How can this be? Press F9 to place a break point. Press F5 to enter debug mode and run it to the break point which you placed at Shape shape = new Text();. Next, press F10.
The second line in the above code is an example of downcasting. We are using a cast. Below is a screenshot of what it looks like in Visual Studio in debug mode using a Watch Window and a breakpoint. Note that when we downcast we have full access to the properties and methods of the Text class. We had access to FontSize.
Downcasting in WPF
A real-world example of downcasting can be found in a Windows Presentation Foundation project. Create a new project.
In the Toolbox on the left side of the IDE, under Common WPF Controls, find the Button. Drag it into the window. Double-click the button. Now you can type code. Just to test things out we can display a message box when the user clicks the button.
The properties of sender do not include anything about the button class, as you can see from the screenshot above. So the code below is what we have after we typed in our message box and the rest of the solution.
So you can use an explicit cast or the as keyword. You have two options. The code above shows both options. Use an explicit cast when you are sure of the type and the as keyword when there is doubt.