enum 是IEnumerable 在generics方法中返回true

这是此问题的后续内容: 对通用枚举集合应用的Cast .Cast 会导致无效的强制转换exception

enum Gender { Male, Female } Gender g = Gender.Male; bool b = g is int; // false, alright no issues b = new[] { g } is IEnumerable; // false, alright no issues b = Is(g); //false, alright no issues b = Is<Gender[], IEnumerable>(new[] { g }); // true, why on earth !!! static bool Is(S s) { return s is T; } 

为什么Gender[] is IEnumerable在通用情况下返回true ? 特别是当它们不兼容时?

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

在我链接的问题中,它让我感到惊讶! 我认为这个问题是相关问题问题的症结所在。


对于有兴趣的人来说,这是一个带arrays的极端情况(不是真正的枚举)。 请回答Eric Lippert的博客文章,了解更多关于这个边缘案例的文章。 例如, List不会发生这种情况:

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

我认为这是其中C#定义与CLI的isinst定义不同的情况isinst ,显然在检查数组赋值兼容性时将枚举视为其底层基类型。 (Eric Lippert撰写了一篇博客文章 ,解释了为什么uint[]被CLI视为int[]而不是C#;我怀疑同样的解释适用于此。)你甚至不需要generics来certificate:

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

第一个is表达式在编译时被优化为false ,因为C#编译器“知道” Gender[]不是IEnumerable 。 第二个is表达式生成一个isinst指令,在运行时进行评估。 引用Eric Lippert:

遗憾的是,C#和CLI规范在这个小问题上存在分歧,但我们愿意忍受不一致。