C# 无法理解枚举的行为
我在用C#练习枚举,但我无法理解这些枚举的输出C# 无法理解枚举的行为,c#,.net,enums,C#,.net,Enums,我在用C#练习枚举,但我无法理解这些枚举的输出 void Main() { MyEnum a = MyEnum.Top; Console.WriteLine(a); } 对于此测试,我的枚举和输出是 enum MyEnum { Left, Right, Top, Bottom // Top } enum MyEnum { Left, Right, Top = 0, Bottom // Left } 我想在rum时间程序选择第一个值为0的项目,为了确认这一点,
void Main()
{
MyEnum a = MyEnum.Top;
Console.WriteLine(a);
}
对于此测试,我的枚举和输出是
enum MyEnum
{
Left, Right, Top, Bottom // Top
}
enum MyEnum
{
Left, Right, Top = 0, Bottom // Left
}
我想在rum时间程序选择第一个值为0的项目,为了确认这一点,我给底部分配了0的值
然后我想也许程序选择了第一个值为0的项目,但按字母顺序搜索
因此,我将Top更改为Top,并更改了测试用例
我知道没有人以这种方式使用enum,但我想知道enum的这种特殊行为。似乎您已经意识到编译器默认从零开始计数
enum MyEnum
{
Left, Right, Top = 0, Bottom = 0 // Bottom
}
被翻译成这个
.class nested private auto ansi sealed MyEnum
extends [mscorlib]System.Enum
{
.field public specialname rtspecialname int32 value__
.field public static literal valuetype X/MyEnum Left = int32(0)
.field public static literal valuetype X/MyEnum Right = int32(1)
.field public static literal valuetype X/MyEnum Top = int32(0)
.field public static literal valuetype X/MyEnum Bottom = int32(0)
}
运行时实际上大部分时间都与底层类型一起工作。有趣的是这里的这个
static void Main()
{
MyEnum a = MyEnum.Top;
Console.WriteLine(a);
Console.ReadKey();
}
甚至不使用实际的枚举成员:
.method private hidebysig static
void Main () cil managed
{
.maxstack 1
.entrypoint
.locals init (
[0] valuetype X/MyEnum a
)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: box X/MyEnum
IL_0009: call void [mscorlib]System.Console::WriteLine(object)
IL_000e: nop
IL_000f: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0014: pop
IL_0015: ret
}
它只使用值0。使用Console.WriteLine打印哪个名称的决策从System.Enum.ToString
开始,在System.Type.GetEnumName(object)
中达到高潮
正如您所见,搜索要打印的名称的实际方法是通过字段名(通过反射找到)进行二进制搜索
不过,这只是当前的实现,可能会因编译器和/或运行时版本的不同而有所不同。语言规范不保证上述代码的任何特定顺序或结果。枚举只是命名某个常量
就像我们有一些水果。苹果,香蕉,橘子。我们有一个场景,如果一个婴儿1岁,它会变成橙色,如果2岁,它会变成香蕉,如果3岁,它会变成苹果。那么我们怎么写呢
一种解决方案是:
int fruiteType = 0;
if(ageOfBaby == 1)
fruiteType == 1;//assuming Orange = 1;
if(ageOfBaby == 2)
fruiteType == 2;//assuming Banana = 2;
if(ageOfBaby == 3)
fruiteType == 3;//assuming Apple = 3;
我们可以巧妙地使用Enum实现这一点。比如:
enum Fruits {Orange, Banana, Apple};
int fruiteType = 0;
if(ageOfBaby == 1)
fruiteType == (int)Fruits.Orange;
if(ageOfBaby == 2)
fruiteType == (int)Fruits.Banana;
if(ageOfBaby == 3)
fruiteType == (int)Fruits.Apple;
默认情况下,在上述条件下,您将分别在水果类型变量中获得0、1和2。如果要更改默认值,可以定义如下:
enum Fruits {Orange = 1, Banana, Apple};
为什么这很重要。当我们假设这样的值时,我们可能会忘记序列,从而造成麻烦。但是当我们给它们命名时,我们永远不会忘记哪个值代表着水果类型=1
谢谢但是当我给3个枚举分配相同的值时,为什么输出会发生变化(我假设左侧自动分配为0,由我显式分配为2)。好吧,通过使用相同枚举值的多个枚举值,可以使这些值彼此不可区分。如果您试图打印值的名称,则会输入未定义的行为区域,这意味着实现可以免费向您提供任何相关名称。它为什么选择一个而不是另一个是一个实现细节,可能会随时更改。返回哪个枚举名是未记录的行为。这确实是一个rum时间问题;p@LasseV.karlsen它使用二进制搜索查找要显示的名称这一事实是未记录的行为,因此OP不应依赖代码始终为重复值返回相同的名称。此外,仅向枚举添加1个值可能会更改结果。是的,这只是我使用的编译器和运行时版本的当前实现。关于这一点,我已经添加了一段。谢谢你的努力,但这并没有以任何方式回答OP的问题。
int fruiteType = 0;
if(ageOfBaby == 1)
fruiteType == 1;//assuming Orange = 1;
if(ageOfBaby == 2)
fruiteType == 2;//assuming Banana = 2;
if(ageOfBaby == 3)
fruiteType == 3;//assuming Apple = 3;
enum Fruits {Orange, Banana, Apple};
int fruiteType = 0;
if(ageOfBaby == 1)
fruiteType == (int)Fruits.Orange;
if(ageOfBaby == 2)
fruiteType == (int)Fruits.Banana;
if(ageOfBaby == 3)
fruiteType == (int)Fruits.Apple;
enum Fruits {Orange = 1, Banana, Apple};