c# - enum[] 是 IEnumerable<int> 在泛型方法中返回 true

标签 c# generics enums typechecking

这是这个问题的后续:Cast<int>.Cast<int?> applied on generic enum collection results in invalid cast exception

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;
}

为什么会这样 Gender[] is IEnumerable<int>返回 true在一般情况下?尤其是当它们类型不兼容时?

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

它在我链接的问题中绊倒了我!我认为这个问题是链接问题的症结所在。


对于感兴趣的人来说,这是数组(不是真正的枚举)的极端情况。关注Eric Lippert's blog答案中的文章以了解有关此边缘案例的更多信息。 List<T> 不会发生这种情况例如:

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

最佳答案

我认为这是 C# 定义 is 的情况之一。不同于 CLI 对 isinst 的定义,在检查数组赋值兼容性时,它显然将枚举视为它们的基础基类型。 (Eric Lippert 写了一个 blog post 解释了为什么 uint[] 被 CLI 而不是 C# 视为 int[];我怀疑同样的解释适用于这里。)你甚至不需要泛型来演示:

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

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

It is unfortunate that C# and the CLI specifications disagree on this minor point but we are willing to live with the inconsistency.

关于c# - enum[] 是 IEnumerable<int> 在泛型方法中返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20292988/

相关文章:

c# - WPF 组合框如果只有 1 项则自动选择

java - 扩展通用抽象类 : Correct Bounding

java - 如何从通用枚举类型中检索常量的接口(interface)?

c# - 为什么这个方法重载异常?

c# - 用于加载 RTMP 源的应用程序的视频播放器

java - 为什么我不能用接口(interface)来做这个?

swift - Swift 3 中通用协议(protocol)类型的变量

enums - 枚举 Elixir 数据(包括嵌套)并在 EEx 中显示键/值?

java - 为什么 if 语句检测不到我的游戏状态

c# - DocumentSaved 事件永远不会引发