![](/img/trans.png)
[英]How to validate enum in DTO so it contains valid values for that enum type?
[英]How to convert primitive type value to enum value, when enum contains elements with the same values?
我寫了代碼:
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);
}
}
}
我希望在輸出中看到:
只有短名
0 NO
1 R2
2 FX
3 FY
4 D1
5 D2
6 RC
7 RN
或只是長名
0 None
1 RotateTwice
2 FlipX
3 FlipY
4 ReflectDiagonal1
5 ReflectDiagonal2
6 RotateClockwise
7 RotateNonClockwise
或按字母順序排序后首先出現的名稱,在這種情況下與“僅短名稱”重合。
但我沒想到會看到該節目出現的內容:
0 None
1 RotateTwice
2 FlipX
3 FlipY
4 ReflectDiagonal1
5 ReflectDiagonal2
6 RotateClockwise
7 RN
輸出結尾的短名稱。 ¿為什么?
我試圖重新排列枚舉中的列:
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);
}
}
}
我再次對輸出感到驚訝:
0 NO
1 R2
2 FX
3 FY
4 D1
5 D2
6 RC
7 RotateNonClockwise
¿為什么? 請向我解釋這里發生了什么。
枚舉變量基本上只是一個數字,它沒有附加標簽(如R2
)。 例如, FlipRotate2dEnum.RN
和FlipRotate2dEnum.RotateNonClockwise
是相同的,因為它們具有相同的值7.實際上,如果你這樣做:
Console.WriteLine(FlipRotate2dEnum.RotateNonClockwise);
您將看到RN
作為輸出。 如Enum.ToString()
文檔中Enum.ToString()
如果多個枚舉成員具有相同的基礎值,並且您嘗試根據其基礎值檢索枚舉成員名稱的字符串表示形式,則您的代碼不應對該方法將返回的名稱做出任何假設
但是如果你很好奇你所看到的確切結果是如何在內部得到的,請閱讀以下內容。
首先,基本值的數組(在您的情況下 - 字節) 大致是這樣獲得的(但不完全像這樣):
byte[] values = Enum.GetValues(typeof(FlipRotate2dEnum)).Cast<byte>().ToArray();
它不包含不同的值,只包含枚舉中的所有值,已排序。 所以在這種情況下16個值:
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7
然后獲得名稱數組(再次,不完全像這樣,但以類似的方式)。 此數組也按相應的值排序(即 - 值0的名稱在值1的名稱前面等):
var names = Enum.GetNames(typeof(FlipRotate2dEnum));
它還包含16個名稱:
NO, None, R2, RotateTwice, ...
然后,對給定值的值數組執行二進制搜索 。 假設我們調用FlipRotate2dEnum.RotateNonClockwise.ToString()
。 它的值為7,因此對7執行二進制搜索:
var index = Array.BinarySearch(values, (byte)7)
然后,結果索引用於獲取名稱:
var name = names[index];
現在,如果你知道二進制搜索是如何工作的 - 你現在應該理解為什么結果不是你所期望的。 對於二進制搜索值,不會按照它們的定義方式按順序進行探索,而是從中間開始搜索,並在每次迭代時將搜索空間減少一半,因此在枚舉枚舉聲明時,您的值映射到哪個名稱並不是很明顯。
當然你可以通過交換RN
和RotateNonClockwise
來達到你想要的效果,但我希望你從上面了解到這不是一個好主意,更不用說你會依賴於實現細節,而addind \\刪除新成員會很痛苦。
如評論中所述 - 如果您需要為您的枚舉“顯示”名稱 - 用某些屬性裝飾它們並使用它。 盡量避免使用多個名稱映射到相同值的枚舉,但如果這樣做 - 至少不要將其視為值和名稱之間的一對一映射,因為這不是它的工作原理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.