c# - 为什么 Byte 被提升为 Enum?

标签 c# enums

虽然使用了一个外部 API,该 API 具有多个采用不同数据类型但没有枚举的重载,但我决定创建一个方便的方法来为枚举提供更多类型安全性,并最终得到如下内容:

namespace TestEnumPromotion
{
    enum Values
    {
        Value0,
        Value1,
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Prints int
            Overloaded(0);

            // Prints Values
            Overloaded(Values.Value0);

            // Does not compile! :-/
            Overloaded((byte) 0);

            // Prints int
            byte b = 0;
            Overloaded(b);
        }

        static void Overloaded(int i)
        {
            Console.WriteLine("int");
        }

        static void Overloaded(Values i)
        {
            Console.WriteLine("Values");
        }
    }
}

但是我很惊讶地看到代码没有编译,因为Overloaded((byte) 0):

The call is ambiguous between the following methods or properties: 'Program.Overloaded(int)' and 'Program.Overloaded(Values)'

但是byte不能自动提升为Values,即Values v = (byte)b不会编译,因为:

Cannot implicitly convert type 'byte' to '`TestEnumPromotion.Values`'.

所以唯一可能的重载应该是 int,对吧?

我认为也许枚举只是语法糖,编译器会生成接收 int 的方法,但通过 ILDASM 查看 IL 表明实际上创建了一个采用枚举的方法。

.method private hidebysig static void  Overloaded(valuetype TestEnumPromotion.Values i) cil managed
{
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "Values"
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
} // end of method Program::Overloaded

发生了什么事?

最佳答案

这是语言中一个奇怪的小规则的结果:文字 0 可以隐式转换为任何 enum

更新:根据评论和链接的来源,编译器实际上并不遵循规范。编译器允许隐式转换任何零常量,而不仅仅是文字零。您可以阅读有关此问题的更多信息 here .

这不会编译:

Values someValue = 1; //can not implicitly convert `int` to...

但是,有趣的是,这将:

Values someValue = 0;

在您的情况下,因为 (byte)0(常量零)可以隐式转换为 Valuesint,编译器不能选择最佳过载失败无法解决调用。如果您将代码更改为 (byte)1 或任何其他文字值,它会编译得很好。

值得一提的是,Overloaded(0) 起作用的原因仅仅是因为编译器找到了精确匹配;不需要隐式转换,因此 Overloaded(int i) 毫无争议地获胜。

引用 c# 4.0 规范:

1.10 (...) The default value of any enum type is the integral value zero converted to the enum type. In cases where variables are automatically initialized to a default value, this is the value given to variables of enum types. In order for the default value of an enum type to be easily available, the literal 0 implicitly converts to any enum type.(...)

关于c# - 为什么 Byte 被提升为 Enum?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49413932/

相关文章:

c# - 在 Web 应用程序而非控制台中运行时,linq2db InformixDataProvider 抛出的类型初始化程序错误

c# - 对于在后台运行且没有 UI 的 C# 程序,我应该使用什么类型的项目?

c++ - 对静态数组的初始值设定项列表大小错误发出警告

sql - 如何在 SQL 查询中显示枚举字符串键而不是整数值?

java - 导入无法解决?

c# - 为什么 System.Threading.Timer 会自行停止?

c# - 我可以将外部配置与 ASP.NET Core 的默认依赖注入(inject)一起使用吗?

c# - 如何更改 Windows Phone 中同一个 ListBox 中另一个对象的可见性?

performance - 为什么 Python 枚举很慢?

java - JAXB:将 XML 枚举验证为字符串,同时在 XSD 中保留类型