2009-12-08 3 views
6

Doublons possibles:
Enumerable.Cast<T> extension method fails to cast from int to long, why ?
Puzzling Enumerable.Cast InvalidCastException
Cast/Convert IEnumerable<T> to IEnumerable<U> ?Pourquoi ne pas diffuser <double>() travail sur IEnumerable <int>?

Je suis en train de convertir un tableau d'entiers à un tableau de doubles (donc je peux passer à une fonction qui prend un tableau de doubles).

La solution la plus évidente (pour moi, au moins) est d'utiliser la fonction d'extension Cast pour IEnumerable, mais elle me donne une exception InvalidCastException, et je ne comprends pas pourquoi. Ma solution consiste à utiliser Select à la place, mais je pense que Cast semble plus propre.

Quelqu'un pourrait-il me dire pourquoi la méthode Cast ne fonctionne pas?

Espérons que le code ci-dessous illustre mon problème:

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 

    class Program 
    { 
     static void Main() 
     { 
      var intArray = new[] { 1, 2, 3, 4 }; 
      PrintEnumerable(intArray, "intArray: "); 

      var doubleArrayWorks = intArray.Select(x => (double)x).ToArray(); 
      PrintEnumerable(doubleArrayWorks, "doubleArrayWorks: "); 

      // Why does this fail?? 
      var doubleArrayDoesntWork = intArray.Cast<double>().ToArray(); 
      PrintEnumerable(doubleArrayDoesntWork, "doubleArrayDoesntWork: "); 

      // Pause 
      Console.ReadLine(); 
     } 

     private static void PrintEnumerable<T>(
      IEnumerable<T> toBePrinted, string msgPrefix) 
     { 
      Console.WriteLine(
       msgPrefix + string.Join(
        ",", toBePrinted.Select(x => x.ToString()).ToArray())); 
     } 
    } 

}

+0

Ooops ... Je n'ai pas vérifié avec soin le débordement de la pile avant de le demander. J'ai trouvé ma question a déjà été posée et a répondu: http://stackoverflow.com/questions/1684448/enumerable-castt-extension-method-fails-to-cast-from-int-to-long-why – dominic

Répondre

2

Essayez d'utiliser la méthode convertall de la classe Array. Cela vous donne un contrôle explicite sur la conversion.

var doubleArray = Array.ConvertAll<int, double>(intArray, num => (double)num); 

Cela contourne l'erreur interne que vous rencontrez.

D'autres méthodes vous permettent également de contrôler explicitement le processus de conversion.

+1

C'est pareil en utilisant select. – Dykam

9

Le problème vient du fait que les opérateurs cast (surchargés) sont résolus au moment de la compilation. Essayez de penser à la façon dont Cast est implémenté. Je parie que le code ressemble à ceci:

public static IEnumerable<T> Cast<T>(this IEnumerable source) 
{ 
    foreach(object element in source) 
    { 
     yield return (T)(object)element; 
    } 
} 

Toutes les informations du compilateur a est qu'il doit jeter un objet à un T. de type et qu'il utilisera la coulée de l'héritage par défaut. Aucun opérateur surchargé personnalisé ne sera utilisé. Et dans votre exemple, un int n'est pas un double, donc la distribution échouera.

L'exemple de sélection:

source.Select(a => (double)a)); 

fonctionne parce que le compilateur connaît deux types et il est en mesure d'appeler l'opérateur surchargé approprié.

+0

La chose principale à observer ici est probablement que le _syntax_ typecast est utilisé à la fois pour les opérateurs de conversion typecasts _and_. Les conversions entre types numériques sont des opérateurs de conversion, pas des conversions. – Joey

Questions connexes