Summary: in this tutorial, you’ll learn about the C# casting including upcasting and downcasting.
Introduction to C# casting
C# is a statically-typed programming language. It means that after you declare a variable, you cannot redeclare it. Also, you cannot reassign a value of another type to the variable unless that type is implicitly compatible with the variable’s type.
An object reference can be:
- Implicitly upcast to a base class reference. An upcast always succeeds.
- Explicitly downcast to a subclass reference. A downcast only succeeds if the objects are compatible types.
Upcasting
An upcast creates a base class reference from a subclass reference. For example:
class Person
{
public string Name { get; set; }
}
class Employee: Person
{
public string JobTitle { get; set; }
}
Code language: C# (cs)
var employee = new Employee()
{
Name = "John Doe",
JobTitle = "C# Developer"
};
Person person = employee;
Code language: C# (cs)
In this example:
- First, define the
Employee
class that inherits from thePerson
class. ThePerson
class is a base class and theEmployee
class is a subclass. - Second, create a new instance of the
Employee
class and assign it to theemployee
variable. - Third, assign the object referenced by the
employee
variable to a reference of thePerson
class.
After upcasting, the variable person
still references the same Employee
‘s object. Both employee
and person
variable reference the same Employee
‘s object. The object itself does not change.
Although the person
and employee
variables refer to the same object, the person
has a more restrictive view on that object. For example, it can only access the Name
property but cannot access the JobTitle
property of the object.
The following statement will cause a compile-time error:
person.JobTitle;
Code language: C# (cs)
Error:
'Person' does not contain a definition for 'JobTitle'...
Code language: plaintext (plaintext)
Downcasting
A downcast operation creates a subclass reference from a base class reference. A downcast requires a cast expression with the following syntax:
(T)E
Code language: C# (cs)
The cast expression explicitly converts the result of the expression (E
) to the type T
. If no explicit conversion exists from the type of E
to type T
, the compiler will raise an error.
Also, at runtime, the explicit conversion might fail and the cast expression might throw an exception.
The following example illustrates the downcasting:
var employee = new Employee()
{
Name = "John Doe",
JobTitle = "C# Developer"
};
Person person = employee; // upcast
Employee employee2 = (Employee)person; // downcast
Console.WriteLine(employee2.Name);
Console.WriteLine(employee2.JobTitle);
Code language: C# (cs)
In this example, the downcast operation explicitly converts the object referenced by the person
reference to the employee2
.
Since the employee2
variable refers to the Employee
object, it can access all properties of the Employee
‘s object.
The following defines the Candidate
class that inherits from the Person
class:
class Person
{
public string Name { get; set; }
}
class Employee : Person
{
public string JobTitle { get; set; }
}
class Candidate : Person
{
}
Code language: C# (cs)
The following downcast will fail at runtime:
var employee = new Employee()
{
Name = "John Doe",
JobTitle = "C# Developer"
};
Person person = employee; // upcast
Candidate candidate = (Candidate)person; // downcast fail at runtime
Code language: C# (cs)
In this example, the person
variable references an instance of the Employee
class. However, we cast it as an instance fo the Candidate
class, which is not an instance of the Employee
class.
If you run the program, you’ll get the following exception:
System.InvalidCastException: 'Unable to cast object of type 'Employee' to type 'Candidate'.'
Code language: plaintext (plaintext)
The as operator
If a downcast fails, it’ll throw an exception at runtime. If you don’t want this behavior, you can use the as
operator.
The as
operator performs a downcast that evaluates to null
rather than throwing an exception if the downcast fails. This allows you to subsequentially check whether the result of the downcast is null or not. For example:
var employee = new Employee()
{
Name = "John Doe",
JobTitle = "C# Developer"
};
Person person = employee;// upcast
Candidate candidate = person as Candidate;
if (candidate != null)
{
Console.WriteLine(candidate.Name);
}
Code language: C# (cs)
In this example, the downcast fails. Therefore, the candidate
variable is null. Then, we check whether the candidate
is null or not before displaying its name
property to the console.
Summary
- An object reference can be implicitly upcast to a base class reference. An upcast always succeeds.
- An object reference can also be explicitly downcast to a subclass reference. A downcast succeeds only if the object is compatible typed.
- Use the
as
operator to perform a downcast that evaluates tonull
rather than throwing an exception.