2014-03-02 76 views
2

我花了幾個小時試圖找出將Enum掩碼轉換爲Enum值數組的一般方式,相反,Enum值數組枚舉掩碼。將標誌轉換爲IEnumerable的擴展方法<Enum>反過來(C#)

寫一個擴展方法這樣做是有點痛苦,所以我只是想分享我的解決方案,以防它可以幫助某人。我相信它可以改進,但在這裏!

+0

爲什麼你想要將枚舉掩碼轉換爲枚舉數組?你會怎麼做,你不能直接使用面膜? – Chris

+0

還有天哪。它真的很煩人的擴展方法的枚舉是不是?你可以做'enums.Aggregate((x,y)=> x | y);'作爲一個非常快速的方法來枚舉值來屏蔽,但由於所有其他代碼你需要包裝它來處理轉換等 – Chris

+0

我的數據庫包含掩碼,但我的REST API公開了值列表。所以我需要一種方便來回的方法。我沒有想過總計,你有一個好點! – Pedro

回答

5

下面的擴展方法從枚舉值列表返回一個掩碼。

public static T ToMask<T>(this IEnumerable<T> values) where T : struct, IConvertible 
{ 
    if (!typeof(T).IsEnum) 
     throw new ArgumentException("T must be an enumerated type."); 

    int builtValue = 0; 
    foreach (T value in Enum.GetValues(typeof(T))) 
    { 
     if (values.Contains(value)) 
     { 
      builtValue |= Convert.ToInt32(value); 
     } 
    } 
    return (T)Enum.Parse(typeof(T), builtValue.ToString()); 
} 

下面的擴展方法返回一個掩碼的枚舉值列表。

public static IEnumerable<T> ToValues<T>(this T flags) where T : struct, IConvertible 
{ 
    if (!typeof(T).IsEnum) 
     throw new ArgumentException("T must be an enumerated type."); 

    int inputInt = (int)(object)(T)flags; 
    foreach (T value in Enum.GetValues(typeof(T))) 
    { 
     int valueInt = (int)(object)(T)value; 
     if (0 != (valueInt & inputInt)) 
     { 
      yield return value; 
     } 
    } 
} 

需要注意的是:在C#(where T : ...

  1. 泛型約束不能限制噸至枚舉
  2. 這些方法不檢查枚舉是否具有[Flags]屬性(不能找出答案)

用法:

[Flags] 
public enum TestEnum : int 
{ 
    None = 0, 
    Plop = 1, 
    Pouet = 2, 
    Foo = 4, 
    Bar = 8 
} 

要掩模:

TestEnum[] enums = new[] { TestEnum.None, TestEnum.Plop, TestEnum.Foo }; 
TestEnum flags = enums.ToMask(); 

TestEnum expectedFlags = TestEnum.None | TestEnum.Plop | TestEnum.Foo; 
Assert.AreEqual(expectedFlags, flags); 

要值:

TestEnum flags = TestEnum.None | TestEnum.Plop | TestEnum.Foo; 
TestEnum[] array = flags.ToValues().ToArray(); 

TestEnum[] expectedArray = new[] { TestEnum.Plop, TestEnum.Foo }; 
CollectionAssert.AreEqual(expectedArray, array); 
+0

非常好的擴展方法,謝謝。 – Lopsided

3

我需要一個簡單的解決方案,用於將相反的方向(而不是必須包括擴展名),所以這裏的一個LINQ溶液到將你枚舉的IEnumerable變成標記的枚舉:

MyEnum e = MyEnumList.Aggregate((MyEnum)0, (a,b) => a |= b); 
相關問題