簡體   English   中英

當枚舉包含具有相同值的元素時,如何將原始類型值轉換為枚舉值?

[英]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.RNFlipRotate2dEnum.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];

現在,如果你知道二進制搜索是如何工作的 - 你現在應該理解為什么結果不是你所期望的。 對於二進制搜索值,不會按照它們的定義方式按順序進行探索,而是從中間開始搜索,並在每次迭代時將搜索空間減少一半,因此在枚舉枚舉聲明時,您的值映射到哪個名稱並不是很明顯。

當然你可以通過交換RNRotateNonClockwise來達到你想要的效果,但我希望你從上面了解到這不是一個好主意,更不用說你會依賴於實現細節,而addind \\刪除新成員會很痛苦。

如評論中所述 - 如果您需要為您的枚舉“顯示”名稱 - 用某些屬性裝飾它們並使用它。 盡量避免使用多個名稱映射到相同值的枚舉,但如果這樣做 - 至少不要將其視為值和名稱之間的一對一映射,因為這不是它的工作原理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM