leo*_*n01 6 .net c# enums type-conversion explicit-conversion
我写了代码:
enum FlipRotate2dEnum : byte {
NO = 0, None = 0,
R2 = 1, RotateTwice = 1,
FX = 2, FlipX = 2,
FY = 3, FlipY = 3,
D1 = 4, ReflectDiagonal1 = 4,
D2 = 5, ReflectDiagonal2 = 5,
RC = 6, RotateClockwise = 6,
RN = 7, RotateNonClockwise = 7
}
class EnumTest {
public static void Main() {
for(byte i = 0; i < 8; ++i) {
FlipRotate2dEnum v = (FlipRotate2dEnum)i;
System.Console.WriteLine("{0} {1}", i, v);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望在输出中看到:
只有短名
0 NO
1 R2
2 FX
3 FY
4 D1
5 D2
6 RC
7 RN
Run Code Online (Sandbox Code Playgroud)
或只是长名
0 None
1 RotateTwice
2 FlipX
3 FlipY
4 ReflectDiagonal1
5 ReflectDiagonal2
6 RotateClockwise
7 RotateNonClockwise
Run Code Online (Sandbox Code Playgroud)
或按字母顺序排序后首先出现的名称,在这种情况下与"仅短名称"重合.
但我没想到会看到该节目出现的内容:
0 None
1 RotateTwice
2 FlipX
3 FlipY
4 ReflectDiagonal1
5 ReflectDiagonal2
6 RotateClockwise
7 RN
Run Code Online (Sandbox Code Playgroud)
输出结尾的短名称.¿为什么?
我试图重新排列枚举中的列:
public enum FlipRotate2dEnum : byte {
None = 0, NO = 0,
RotateTwice = 1, R2 = 1,
FlipX = 2, FX = 2,
FlipY = 3, FY = 3,
ReflectDiagonal1 = 4, D1 = 4,
ReflectDiagonal2 = 5, D2 = 5,
RotateClockwise = 6, RC = 6,
RotateNonClockwise = 7, RN = 7
}
class EnumTest {
public static void Main() {
for(byte i = 0; i < 8; ++i) {
FlipRotate2dEnum v = (FlipRotate2dEnum)i;
System.Console.WriteLine("{0} {1}", i, v);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我再次对输出感到惊讶:
0 NO
1 R2
2 FX
3 FY
4 D1
5 D2
6 RC
7 RotateNonClockwise
Run Code Online (Sandbox Code Playgroud)
¿为什么? 请向我解释这里发生了什么.
枚举变量基本上只是一个数字,它没有R2附加标签(例如 )。例如,FlipRotate2dEnum.RN和FlipRotate2dEnum.RotateNonClockwise是同一件事,因为它们具有相同的值 7。实际上,如果你这样做:
Console.WriteLine(FlipRotate2dEnum.RotateNonClockwise);
Run Code Online (Sandbox Code Playgroud)
您将看到RN输出。正如文档中所述Enum.ToString()
如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应对该方法将返回哪个名称做出任何假设
但如果您好奇您所看到的结果到底是如何在内部获得的,请阅读以下内容。
首先,基本值数组(在您的情况下为字节)大致如下获取(但不完全像这样):
byte[] values = Enum.GetValues(typeof(FlipRotate2dEnum)).Cast<byte>().ToArray();
Run Code Online (Sandbox Code Playgroud)
它不包含不同的值,仅包含枚举中的所有值(已排序)。所以在这种情况下有 16 个值:
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7
Run Code Online (Sandbox Code Playgroud)
然后获得名称数组(同样,不完全像这样,但以类似的方式)。该数组也按相应的值排序(即,值 0 的名称位于值 1 的名称之前,等等):
var names = Enum.GetNames(typeof(FlipRotate2dEnum));
Run Code Online (Sandbox Code Playgroud)
它还包含 16 个名称:
NO, None, R2, RotateTwice, ...
Run Code Online (Sandbox Code Playgroud)
然后,对给定值的值数组执行二分搜索。说我们打电话FlipRotate2dEnum.RotateNonClockwise.ToString()。它的值为 7,因此对 7 执行二分查找:
var index = Array.BinarySearch(values, (byte)7)
Run Code Online (Sandbox Code Playgroud)
然后,生成的索引用于获取名称:
var name = names[index];
Run Code Online (Sandbox Code Playgroud)
现在,如果您知道二分搜索的工作原理 - 您现在应该明白为什么结果与您期望的不完全一样。使用二分搜索时,值不会按照定义的方式按顺序探索,而是从中间开始搜索,并在每次迭代时将搜索空间减少一半,因此在枚举声明中加注星号时,值映射到哪个名称并不是很明显。
当然,您只需交换RN和即可达到您想要的结果RotateNonClockwise,但我希望您从上面了解到这不是一个好主意,更不用说您将依赖于实现细节,并且添加\删除新成员将是一个痛苦。
正如评论中所述 - 如果您需要枚举的“显示”名称 - 用某些属性装饰它们并使用它。尽量避免将多个名称映射到同一值的枚举,但如果这样做,至少不要将其视为值和名称之间的一对一映射,因为这不是它的工作原理。