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规范在这个小问题上存在分歧,但我们愿意忍受不一致。