Comprendre InvalidCastException
avec IEnumerable.Cast
Tenter de lancer un IEnumerable<int>
vers un IEnumerable<long>
en utilisant Cast<T>
aboutit souvent à un InvalidCastException
perplexe. Cette opération apparemment simple échoue en raison d'un mécanisme subtil au sein de la méthode Cast<T>
. Prenons cet exemple :
<code class="language-csharp">IEnumerable<int> list = new List<int>() { 1 }; IEnumerable<long> castedList = list.Cast<long>(); Console.WriteLine(castedList.First());</code>
La cause profonde : boxe et déballage
La clé pour comprendre cela réside dans le fonctionnement de Cast<T>
. C'est une méthode d'extension sur IEnumerable
, pas sur IEnumerable<T>
. Cela signifie que chaque élément du IEnumerable<int>
est d'abord encadré dans un System.Object
avant que la conversion vers long
ne soit tentée. Ceci est fonctionnellement équivalent à :
<code class="language-csharp">int i = 1; object o = i; // Boxing long l = (long)o; // Unboxing and Cast - This throws the exception!</code>
Le InvalidCastException
se produit lors de l'étape de unboxing. Bien qu'un casting direct de int
à long
soit valide, le déballage d'un int
en boîte vers un long
ne l'est pas.
Résolution
Pour éviter cela InvalidCastException
, utilisez une méthode qui gère la conversion dans le contexte IEnumerable<T>
fortement typé, telle que 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>
Cette approche effectue le casting directement sur chaque int
élément avant que la boxe ne se produise, empêchant ainsi le InvalidCastException
. Utiliser Select
fournit une solution plus propre et plus efficace que de compter sur Cast<T>
pour ce type de conversion.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!