为什么在使用枚举代替其基础类型时必须使用显式强制转换?
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
。这就是为什么它仍然需要显式转换。
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
。这就是为什么它仍然需要显式转换。