Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To cast a C# object referenced by a parent (base) class variable to a child (derived) class, the object must already have that derived runtime type. Use a type pattern such as if (animal is Dog dog) when the cast might fail; it checks compatibility and gives you a safely typed variable inside the successful branch. A cast does not turn a base-class object into a derived-class object.

What a parent-to-child cast does

In C#, a variable’s declared type and the object it references can differ. Assigning a derived object to a base-class variable is an implicit upcast; converting that reference back to a derived type is a downcast and requires a runtime check. Microsoft Learn explains that a base-to-derived conversion needs an explicit check because the object may not be the derived type you expect: C# type conversion documentation.

For example, Animal animal = new Dog(); is valid because a Dog is an Animal. The variable animal can refer to the existing Dog object, but its declared type exposes only members available through Animal. A successful downcast lets code access Dog-specific members.

Choose how to handle a possible mismatch

Approach What happens if the object is incompatible Use it when
Type pattern: is Dog dog The condition is false; the body does not run. A mismatch is an expected possibility and code should run only for matching objects.
as operator The result is null for an incompatible reference type. A nullable result fits the surrounding code and you will check it before use.
Explicit cast: (Dog)animal An incompatible object causes InvalidCastException. The program has already established the type invariant and a violation should surface as an exception.

These forms do not make an incompatible object compatible; they differ in how they report a failed conversion. See Microsoft’s type-testing and cast operator reference, the C# conversion rules, and the InvalidCastException API documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended for uncertain types: pattern matching

class Animal { }
class Dog : Animal
{
    public void Bark() { }
}

Animal animal = new Dog();

if (animal is Dog dog)
{
    dog.Bark();
}

The condition tests whether the object can be treated as a Dog. When it succeeds, dog is the converted reference and can be used in the branch. If animal is null or refers to an incompatible object, the branch is skipped.

Use as when null is the failure result

Dog? dog = animal as Dog;

if (dog != null)
{
    dog.Bark();
}

For a reference type, as returns null when the referenced object is not compatible with the target type. Check the result before calling derived-class members. Nullable-reference-type annotations and compiler warnings depend on the project’s nullable settings.

Use an explicit cast when compatibility is guaranteed

Dog dog = (Dog)animal;
dog.Bark();

This form is concise when earlier logic guarantees that animal references a Dog or a type derived from Dog. If that guarantee is wrong, the cast throws InvalidCastException.

Why a base object cannot be cast into a child object

This does not work:

Animal animal = new Animal();
Dog dog = (Dog)animal; // Throws InvalidCastException

The object was constructed as an Animal, not a Dog. Changing the reference’s declared type cannot add the state or behavior of a derived object. If you need a Dog, create or obtain one. If the goal is to transform data from one object into another, use an explicit constructor or factory rather than a cast.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When repeated downcasts signal a design issue

If many parts of the program repeatedly check which concrete child class they have, consider whether the shared operation belongs on a virtual base-class member or an interface. That can let code work with the shared behavior without inspecting each concrete type. Use downcasting when code genuinely needs a derived-only capability, not as a substitute for defining a suitable shared contract.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.