InvalidCastException
を IEnumerable.Cast
IEnumerable<int>
を使用して IEnumerable<long>
を Cast<T>
にキャストしようとすると、多くの場合、複雑な InvalidCastException
が生成されます。 この一見単純な操作は、Cast<T>
メソッド内の微妙なメカニズムにより失敗します。次の例を考えてみましょう:
<code class="language-csharp">IEnumerable<int> list = new List<int>() { 1 }; IEnumerable<long> castedList = list.Cast<long>(); Console.WriteLine(castedList.First());</code>
根本原因: ボックス化とボックス化解除
これを理解する鍵は、Cast<T>
がどのように機能するかにあります。 これは IEnumerable
ではなく IEnumerable<T>
の拡張メソッドです。これは、IEnumerable<int>
へのキャストが試行される前に、 内の各要素がまず に System.Object
ボックス化long
されることを意味します。 これは機能的には以下と同等です:
<code class="language-csharp">int i = 1; object o = i; // Boxing long l = (long)o; // Unboxing and Cast - This throws the exception!</code>
InvalidCastException
は、ボックス化解除ステップ中に発生します。 int
から long
への直接キャストは有効ですが、ボックス化された int
から long
へのアンボックス化は無効です。
解決策
この InvalidCastException
を回避するには、IEnumerable<T>
: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>
このアプローチでは、ボックス化が発生するint
前に各 要素に対して直接キャストを実行し、InvalidCastException
を防ぎます。 Select
を使用すると、このタイプの変換に Cast<T>
に依存するよりもクリーンで効率的なソリューションが提供されます。
以上が「IEnumerable.Cast」が「InvalidCastException」をスローするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。