投げられたEnumerable.Cast()
InvalidCastException
.NET 3.5 SP1 では、Cast<T>()
を使用して IEnumerable
を変換するときに、不可解なことに InvalidCastException
例外がスローされました。次のコードを考えてみましょう:
<code class="language-csharp">IEnumerable<int> list = new List<int>() { 1 }; IEnumerable<long> castedList = list.Cast<long>(); Console.WriteLine(castedList.First());</code>
なぜこのコードは例外をスローするのでしょうか?
この異常な動作は、.NET 3.5 と .NET 3.5 SP1 の間での Cast<T>()
メソッドの動作の変更に起因します。 SP1 より前では、Cast<T>()
は IEnumerable<T>
に作用し、直接変換が可能でした。ただし、SP1 では、IEnumerable
で動作するように変更されました。つまり、要素は変換前に System.Object
にアンボックス化されます。
このボックス化解除操作の結果は InvalidCastException
になります。これは、int
を long
に直接変換するのとは異なり、ボックス化された int
を long
に変換することは許可されていないためです。実際、このコードは次のことを実行しようとします:
<code class="language-csharp">int i = 1; object o = i; long l = (long)o;</code>
これも同じ InvalidCastException
になります。
解決策と説明
この問題を解決するには、ラムダ式を使用して要素を明示的に変換できます。
<code class="language-csharp">var castedList = list.Select(i => (long)i);</code>
これにより、要素が long
に正常に変換されます。
がこのような動作をする理由は、Cast<T>()
が IEnumerable
の拡張メソッドではなく、IEnumerable<T>
の拡張メソッドであるためです。要素が変換段階に達すると、要素はすでに object
としてボックス化されています。これにより、object
から特定の型に変換すると InvalidCastException
が生成されます。
以上が.NET 3.5 SP1 で「IEnumerable.Cast()」が「InvalidCastException」をスローするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。