2009-11-17 121 views
6

我寫這決定在.NET枚舉的最高值的方法,所以我可以創建一個BitArray與每個位對應一個枚舉值:尋找最高的價值在枚舉

pressedKeys = new BitArray(highestValueInEnum<Keys>()); 

我需要這個在兩個不同的枚舉,所以我把它變成一個通用的方法:

/// <summary>Returns the highest value encountered in an enumeration</summary> 
/// <typeparam name="EnumType"> 
/// Enumeration of which the highest value will be returned 
/// </typeparam> 
/// <returns>The highest value in the enumeration</returns> 
private static int highestValueInEnum<EnumType>() { 
    int[] values = (int[])Enum.GetValues(typeof(EnumType)); 
    int highestValue = values[0]; 
    for(int index = 0; index < values.Length; ++index) { 
    if(values[index] > highestValue) { 
     highestValue = values[index]; 
    } 
    } 

    return highestValue; 
} 

正如你所看到的,我鑄造Enum.GetValues的返回值()爲int [],而不是EnumType []。這是因爲我不能將EnumType(這是一個泛型類型參數)強制轉換爲int。

該代碼有效。但它有效嗎? 我能否總是將Enum.GetValues()的返回值轉換爲int []?

+0

可能的重複[獲取枚舉的最大值](https://stackoverflow.com/questions/203377/getting-the-max-value-of-an-enum) – palswim 2017-07-20 21:06:38

回答

20

不,您無法安全地轉入int[]。枚舉類型並不總是使用int作爲基礎值。如果你限制自己的枚舉類型有一個基本類型int,它應該是罰款,但。

這感覺就像是你(或I)可以擴展Unconstrained Melody支持,如果你想要的 - 在真正的限制是在編譯時enum類型類型的方式,併爲工作的任何枚舉類型,即使是那些其基礎基礎如longulong

如果沒有無約束旋律,您仍然可以通過使用所有枚舉類型適當地實現IComparable的事實以一般方式來執行此操作。如果你使用的是.NET 3.5,它是一個單行版:

private static TEnum GetHighestValue<TEnum>() { 
    return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max(); 
} 
+0

Jon,爲什麼Microsoft參考說「枚舉元素的默認底層類型是int」,如果我不能將任何其他類型賦值給一個枚舉值,也不是除int32之外的其他整數類型。我只是試圖將3L分配給一個枚舉值,並得到一個編譯錯誤。 – 2009-11-17 07:59:08

+0

感謝您報告循環中的雙絞線分配。我已經自己發現了它,並忍者修正了一個版本,而你一定是在寫你的文章;-) – Cygon 2009-11-17 08:06:46

+2

@AndréPena:*默認*基礎類型是一個枚舉,但是你可以聲明一個枚舉爲「enum Foo :長「而不是(等)。有關更多詳細信息,請參閱C#語言規範。 – 2009-11-17 08:11:25

0

簡單!使用LINQ,你的循環可以用兩行代碼來替代,或者如果你想把它們放在一起,就只用一行代碼。

public partial class Form1 : Form 
{ 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     MyEnum z = MyEnum.Second; 
     z++; 
     z++; 

     //see if a specific value is defined in the enum: 
     bool isInTheEnum = !Enum.IsDefined(typeof(MyEnum), z); 

     //get the max value from the enum: 
     List<int> allValues = new List<int>(Enum.GetValues(typeof(MyEnum)).Cast<int>()); 
     int maxValue = allValues.Max(); 
    } 


} 

public enum MyEnum 
{ 
    Zero = 0, 
    First = 1, 
    Second = 2, 
    Third = 3 
} 
+1

雖然爲什麼要創建一個'List '?有沒有必要緩衝所有的值... – 2009-11-17 08:12:01

+0

你是完全正確的,我可以剛剛寫它爲var max =(從int x in Enum.GetValues(typeof(MyEnum))。AsQueryable()select x).Max();但這不是非常友好的代碼,我想稍微分解一下,使代碼易於閱讀和提供信息。我不認爲「緩衝價值」比循環尋找最高價更不理想。 – slugster 2009-11-17 09:31:58

3

按喬恩斯基特的意見(和太感謝您,slugster),這是更新的代碼,現在用IComparable的,因爲我仍然在目標.NET 2.0。

/// <summary>Returns the highest value encountered in an enumeration</summary> 
/// <typeparam name="EnumType"> 
/// Enumeration of which the highest value will be returned 
/// </typeparam> 
/// <returns>The highest value in the enumeration</returns> 
private static EnumType highestValueInEnum<EnumType>() where EnumType : IComparable { 
    EnumType[] values = (EnumType[])Enum.GetValues(typeof(EnumType)); 
    EnumType highestValue = values[0]; 
    for(int index = 0; index < values.Length; ++index) { 
    if(values[index].CompareTo(highestValue) > 0) { 
     highestValue = values[index]; 
    } 
    } 

    return highestValue; 
} 

對於任何人抓住代碼,你可能想要添加一個額外的檢查,所以它不會炸到空的枚舉。

+0

當然'Array.Sort (values);'會比你的循環更好嗎? – stevehipwell 2009-11-17 08:28:03

+2

它會更短,但是爲什麼要排序完成後我要扔掉的數組?也許我在這裏是微型優化,但Array.Sort()對我來說似乎並不直觀。 – Cygon 2009-11-17 15:11:13