Understanding InvalidCastException
with IEnumerable.Cast
Attempting to cast an IEnumerable<int>
to an IEnumerable<long>
using Cast<T>
often results in a perplexing InvalidCastException
. This seemingly simple operation fails due to a subtle mechanism within the Cast<T>
method. Consider this example:
<code class="language-csharp">IEnumerable<int> list = new List<int>() { 1 }; IEnumerable<long> castedList = list.Cast<long>(); Console.WriteLine(castedList.First());</code>
The Root Cause: Boxing and Unboxing
The key to understanding this lies in how Cast<T>
works. It's an extension method on IEnumerable
, not IEnumerable<T>
. This means each element in the IEnumerable<int>
is first boxed into a System.Object
before the cast to long
is attempted. This is functionally equivalent to:
<code class="language-csharp">int i = 1; object o = i; // Boxing long l = (long)o; // Unboxing and Cast - This throws the exception!</code>
The InvalidCastException
occurs during the unboxing step. While a direct cast from int
to long
is valid, unboxing a boxed int
to a long
is not.
Resolution
To avoid this InvalidCastException
, use a method that handles the cast within the strongly-typed IEnumerable<T>
context, such as Select
:
<code class="language-csharp">IEnumerable<int> list = new List<int>() { 1 }; IEnumerable<long> castedList = list.Select(x => (long)x); Console.WriteLine(castedList.First());</code>
This approach performs the cast directly on each int
element before boxing occurs, preventing the InvalidCastException
. Using Select
provides a cleaner and more efficient solution than relying on Cast<T>
for this type of conversion.
The above is the detailed content of Why Does `IEnumerable.Cast` Throw an `InvalidCastException`?. For more information, please follow other related articles on the PHP Chinese website!