2016-12-15 1 views
8

Tenir compte de la déclaration enum suivante et tableau int:Comment utiliser IEnumerable.Cast <> et .ToArray() pour convertir un tableau int en un tableau enum?

enum Test { None }; 

int[] data = {0}; 

Pour convertir ce tableau int[] à un tableau Test[] nous pouvons simplement faire ceci:

Test[] result = Array.ConvertAll(data, element => (Test)element); 

J'ai d'abord essayé de le faire:

Test[] result = data.Cast<Test>().ToArray(); 

Cependant, cela déclenche une exception lors de l'exécution:

System.ArrayTypeMismatchException: Source array type cannot be assigned to destination array type.

Question Un

Est-il possible de le faire en utilisant LINQ et Cast<> sans erreur, ou dois-je simplement utiliser Array.Convert()?

Question Deux (ajouté après la première question a été répondu correctement)

Exactement pourquoi ça ne marche pas?

Il semble que c'est un cas d'un détail de mise en œuvre s'échapper ... Considérez:

Cela provoque une erreur:

var result = data.Cast<Test>().ToList(); // Happens with "ToList()" too. 

Mais cela ne veut pas:

var result = new List<Test>(); 

foreach (var item in data.Cast<Test>()) 
    result.Add(item); 

Et ni est-ce que:

var result = data.Select(x => x).Cast<Test>().ToList(); 

L'implication claire est qu'une sorte d'optimisation est en cours dans l'implémentation .ToList() qui provoque cette exception.


Addendum:

Cela fonctionne aussi:

List<int> data = new List<int>{0}; 
var result = data.Cast<Test>().ToList(); 

ou

List<int> data = new List<int>{0}; 
var result = data.Cast<Test>().ToArray(); 

Il est seulement si les données d'origine est un tableau qui ne fonctionne pas.

+3

Pourquoi? 'Array.ConvertAll' fonctionne et est plus efficace –

+1

@TimSchmelter Je suppose que c'est vraiment une question académique. –

+2

Et maintenant je suis devenu très intéressé par pourquoi cela ne fonctionne pas ... :) –

Répondre

8

Vous pouvez utiliser .Select(e => (Test)e).

1

Il ne fonctionne pas dans ce cas parce que Cast effectue d'abord le contrôle suivant:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) 
{ 
    IEnumerable<TResult> results = source as IEnumerable<TResult>; 
    if (results != null) 
    return results; 
    // ... the rest of the method 
} 

Il se trouve que pour int[] cette vérification réussit (si int[] que IEnumerable<Test> est non nul). En résultat, Cast ne fait rien du tout, il renvoie le tableau tel quel. Ensuite, lorsque vous appelez ToArray, Array.Copy est appelée.Il essaie de copier du tableau int[] vers le tableau Test[] et échoue en raison d'une incompatibilité de type. Cette exception vous voyez.

+0

Cela ressemble à un bug dans l'implémentation. –

+0

@ MatthewWatson pas vraiment, la raison est décrite ici par exemple: http://stackoverflow.com/a/593799/5311735. En bref, C# et CLR ont des approches quelque peu différentes sur la coulée de tableaux de différents types numériques. Voici la même histoire, car enum est fondamentalement juste un nombre. Vous ne pouvez pas convertir int [] en IEnumerable (ou Test []) - le compilateur ne vous le permettra pas car il pense qu'il n'y a pas de telle converstion. Mais CLR le permet et en cours d'exécution cela se produit réellement. – Evk

1

Parce que le casting fait n'a rien fait, car il pense que la collection est déjà le type de désir

IEnumerable<Test> cast = data.Cast<Test>(); 
    IEnumerable<Test> select = data.Select(e => (Test) e); 

    Console.WriteLine(cast == (IEnumerable<int>) data); //True 
    Console.WriteLine(select == (IEnumerable<int>) data); //False 
    Console.WriteLine(select == cast); //Flase 

que vous pouvez voir le casting IEnumerable est en fait le tableau original. Ainsi, .ToArray essaie de faire quelque chose de similaire à (Test[]) data.ToArray();

+0

Ce qui serait un bug dans l'implémentation, n'est-ce pas? –

+0

@MatthewWatson de mon point de vue, oui – Steve

+0

@matthew: dépend, la méthode Cast n'est pas l'opérateur de casting. C'est plus strict. Donc, ne l'utilisez pas de cette manière. Vous essayez de convertir un int [] en un test []. C'est une conversion. Il existe déjà une méthode de conversion significative et efficace dans la classe Array qui fonctionne –