← Debugging Guides

阅读中文版本

C# InvalidCastException: specified cast is not valid

Fix C# InvalidCastException when an explicit cast targets the wrong type, and use pattern matching or as-cast for safe conversion.

beginnerdebuggingcsharptypes

Symptoms

  • System.InvalidCastException: Unable to cast object of type X to type Y
  • A cast that worked for one value fails for another
  • Unboxing an object to the wrong value type throws

Possible causes

  • An object reference is cast to an unrelated type
  • An object stored as object is unboxed to the wrong value type
  • A collection contains heterogeneous types
  • A serialization or DI type changed but the cast was not updated

Diagnosis steps

Read the runtime types from the message

Interpretation

It names both the actual type and the attempted target, showing exactly where they diverge.

Use pattern matching instead of a cast

if (obj is string s) { ... }

Interpretation

is-patterns succeed only when the type matches, avoiding the exception.

Trace the value origin

Interpretation

Boxing, deserialization, and DI often deliver a base or object type that needs checking before use.

Root cause

An explicit cast asserts the runtime type. When the object is a different type, the CLR throws InvalidCastException — there is no conversion performed. This differs from numeric conversion, which uses Convert or Parse. Boxed value types must be unboxed to their exact type.

Fix

Use `as` with a null check or `is` pattern matching to test type before use, and use Convert/Parse for numeric conversions. In collections, prefer generics so element types are known. When deserialising or resolving from DI, request the concrete type or validate with pattern matching before casting.

Verify the fix

Re-run with a value of the previously failing type; the pattern-matched branch handles it without throwing, and a test covers both matching and non-matching types.

Symptoms

A cast throws InvalidCastException: Unable to cast object of type 'X' to type 'Y'. It often appears only for certain inputs, such as a boxed int where a long was expected.

Diagnosis

Note the two types in the message and inspect the value:

object boxed = 42;      // boxed int
long l = (long)boxed;   // InvalidCastException

Boxed value types must be unboxed to their exact type.

Fix

Use pattern matching and proper numeric conversion:

if (obj is string s) {
    Handle(s);
}

object boxed = 42;
long l = Convert.ToInt64(boxed); // correct numeric conversion

Prefer generics over object collections.

Verification

Re-run with the offending value; the pattern branch or conversion succeeds. A test asserts both a matching and a non-matching type path.

Additional Notes

The message names both runtime types, which is the fastest clue: a boxed integer cast to long, or a base type cast to an unrelated derived type, both fail identically even though the intent differs. Numeric widening needs a proper conversion rather than an explicit narrowing cast, while reference conversions need pattern matching. Enabling nullable reference types and preferring generics over object collections removes most such casts entirely, because the compiler then knows element types and flags unsafe conversions before the code ever runs.