15 votes

enum[] is IEnumerable<int> renvoie true dans une méthode générique

Il s'agit d'un suivi de cette question : Cast<int>.Cast<int?> appliqué sur une collection d'enum générique entraîne une exception de cast invalide

enum Gender { Male, Female }

Gender g = Gender.Male;

bool b = g is int; // false, alright no issues
b = new[] { g } is IEnumerable<int>; // false, alright no issues
b = Is<Gender, int>(g); //false, alright no issues
b = Is<Gender[], IEnumerable<int>>(new[] { g }); // true, why on earth !!!

static bool Is<S, T>(S s)
{
    return s is T;
}

Pourquoi est-ce que Gender[] is IEnumerable<int> renvoie à true dans le cas générique ? Surtout quand ils ne sont pas compatibles entre eux ?

IEnumerable<int> c = new[] { Gender.Male }; //not compilable

Il m'avait fait trébucher dans la question que j'ai liée ! Je pense que cette question est le nœud du problème de la question liée.


Pour ceux que cela intéresse, c'est un cas particulier avec les tableaux (pas vraiment des enums). Suivez Le blog d'Eric Lippert article dans la réponse pour en savoir plus sur ce cas limite. Cela ne se produit pas avec List<T> par exemple :

b = Is<List<Gender>, IEnumerable<int>>(new List<Gender> { g }); // false, rightly

15voto

Michael Liu Points 15764

Je pense que c'est un de ces cas où la définition C# de is diffère de la définition de la CLI isinst qui, de toute évidence, traite les enums comme leur type de base sous-jacent lors de la vérification de la compatibilité des affectations de tableaux. (Eric Lippert a écrit une article de blog qui explique pourquoi uint[] est traité comme un int[] par le CLI mais pas par C# ; je soupçonne que la même explication s'applique ici). Vous n'avez même pas besoin de génériques pour faire la démonstration :

Gender g = Gender.Male;
Console.WriteLine(new[] { g } is IEnumerable<int>); // False
Console.WriteLine((object)new[] { g } is IEnumerable<int>); // True

Le premier is L'expression est optimisée pour false en temps de compilation parce que le compilateur C# "sait" Gender[] n'est pas un IEnumerable<int> . Le deuxième is L'expression génère un isinst qui est évaluée à temps de fonctionnement . Citant Eric Lippert :

Il est regrettable que le C# et les spécifications du CLI soient en désaccord sur ce point mineur, mais nous sommes prêts à vivre avec cette incohérence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X