为什么在使用枚举代替其基础类型时必须使用显式强制转换?

Why must I use an explicit cast when using an enum in place of its underlying type?

public enum Foo : byte 
{
    BAR = 0x00,
    BAZ = 0x01,
    DERP = 0xFF
}

public void AppendAsHex(StringBuilder sb, byte b)
{
    sb.AppendFormat("{0:X}", b);
}

为什么这需要显式转换?

Foo theDerp = Foo.DERP;
AppendAsHex(sb, (byte)theDerp); // Fine
AppendAsHex(sb, theDerp); // Compile Error

不会发生精度损失。该方法声明它只需要 byte,忽略任何 enum 优点。

编辑

如果我们将 enum 换成 byte 并使函数采用另一种数字类型,这会很好地工作,例如:

public void AppendAsHex(StringBuilder sb, uint u)
{
    sb.AppendFormat("{0:X}", u);
}

byte b = 21;

AppendAsHex(sb, b); // Fine

因此,编译器会毫不费力地将数字类型提升为更大的数字类型,但需要强制转换以将 enum:byte 转换为 byte

显然 enum:byte 在技术上不是 Type byte,但编译器肯定可以看到它的类型 System.Enum 并检查enum?

中包含的值的类型

虽然如果使用复杂类型编译器可能无法调整大小是非常合理的,但在这种情况下编译器会完全了解所有内容。我不明白,如果可以提升原语,编译器将如何拒绝 promote/cast 明确声明为原语的东西。

这对我来说似乎不一致,我想更好地理解它。

很简单,因为 C# 是强类型的。枚举值不是 byte 类型,即使您将它的翻译值设置为 byte,因此您必须先将其强制转换为 byte,然后才能将其用于期望类型为 byte 的函数。这与转换另一种类型没有什么不同。

此外,如果您的重点是保持整洁,您可以考虑稍微重写(或重载)您的方法,以便转换对它之外的所有内容都是不可见的。它不会改变解决方案,但假设您将在多个地方重复使用该方法,它会减少代码:

public void AppendAsHex(StringBuilder sb, Foo b)
{
    AppendAsHex(sb, (byte)b);
}
public void AppendAsHex(StringBuilder sb, byte b)
{
    sb.AppendFormat("{0:X}", b);
}

到那时,这会起作用

Foo theDerp = Foo.DERP;
AppendAsHex(sb, theDerp);

查看 the answer here

枚举只能从 System.Enum 继承,所以 ':byte' 所做的只是改变枚举值的表示方式。

The underlying type specifies how much storage is allocated for each enumerator. However, an explicit cast is necessary to convert from enum type to an integral type.

https://msdn.microsoft.com/en-us/library/sbbt4032(v=vs.140).aspx

因此,尽管使用 : 来声明基础类型,但任何枚举的实际基类型都是 System.Enum。这就是为什么它仍然需要显式转换。