2011-09-19 14 views
7

załóżmy, że masz enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};C#: Najlepszy sposób sprawdzenia względem zestawu wartości wyliczeniowych?

W pewnym momencie masz funkcję, która sprawdzi wystąpienie MyEnum i powrócić true, jeśli jest to C, D lub F

bool IsCDF(MyEnum enumValue) 
{ 
    return //something slick 
} 

Pamiętam, że nie było pewne naprawdę zgrabny sposób na przesuwanie bitów i preformowanie tej operacji, która czyta się lepiej niż garść trójskładnikowych zdań, ale dla mojego życia nie pamiętam, co to jest.

Ktoś wie?

+0

http://stackoverflow.com/questions/93744/most-common-c-bitwise-operations/417217#417217 –

Odpowiedz

15

Jeśli sprawiają, że [Flags] enum można przypisać inną wartość bitową (1, 2, 4, 8, 16 ...) do każdej wyliczone wartości. Następnie możesz użyć operacji bitowej, aby określić, czy wartość jest zbiorem możliwych wartości.

Tak więc, aby sprawdzić, czy jest C, D lub F:

bool IsCDF(MyEnum enumValue) 
{ 
    return((enumValue & (MyEnum.C | MyEnum.D | MyEnum.F)) != 0); 
} 

Należy pamiętać, że to nie będzie działać na wartość 0 (w przykładzie 'A'), i musi być uważaj, aby wszystkie wartości wyliczeniowe przekształciły się w unikalne wartości bitów (tj. niezerowe moce dwóch).

Zaletami tej metody są:

  • będzie przybierać zazwyczaj pojedynczą instrukcję procesora do wykonania, natomiast robi trzy oddzielne „czy” czeki odbędzie się 3 lub więcej instrukcji (w zależności od platformy docelowej).
  • Możesz przekazać zestaw wartości, które chcesz przetestować, jako wartość wyliczeniową (jedna liczba całkowita), zamiast korzystać z list wartości wyliczonych.
  • Można wykonywać wiele innych przydatnych operacji przy użyciu operacji bitowych, które byłyby nieporęczne i powolne w przypadku zwykłych metod numerycznych/porównawczych.
+0

Tak, podkładam i wypisuję coś podobnego. Chciałem użyć tego z ConnectionState BCL, który Sadly ma ConnectionState.Zamknięte = 0 - Mogę podnieść wszystko do potęgi dwóch, ale opuszczamy zakres "bycia śliskiej". –

+0

Chociaż, jeżeli lista, na którą czekam, nie zawiera wartości 0, to zawsze powinna zawsze być fałszywa ... –

+0

Tak, spóźniam się o 2 lata - ale odradziłbym to, ponieważ jest niebezpieczny w dłuższej perspektywie. biegać. Niezbyt czytelne, niezbyt czyste. – FrankB

0
return (enumValue & MyEnum.C == MyEnum.C) 
     || (enumValue & MyEnum.D == MyEnum.D) 
     || (enumValue & MyEnum.F == MyEnum.F); 
+1

Nie sądzę, że OP jest zainteresowany tym sposobem sprawdzenia. –

+0

Tak, to jest w zasadzie, jeśli instrukcje, po prostu nie True/False –

5

bym ewentualnie użyć Unconstrained Melody jako sposób na utrzymanie rzeczy uporządkowane:

if (value.HasAny(MyEnum.C | MyEnum.D | MyEnum.E)) 
{ 
    ... 
} 

bym prawdopodobnie wyodrębnić „C, D lub E” trochę do nazwana stałą - ewentualnie w enum sam, gdyby miał znaczenie:

1

Może ta klasa rozszerzenie jest przydatne dla Ciebie:

public static class Flags 
{ 
    /// <summary> 
    /// Checks if the type has any flag of value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool HasAny<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (((int) (object) type & (int) (object) value) != 0); 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Checks if the value contains the provided type. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool Has<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (((int)(object)type & (int)(object)value) == (int)(object)value); 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Checks if the value is only the provided type. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool Is<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (int)(object)type == (int)(object)value; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Appends a value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static T Add<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (T)(object)(((int)(object)type | (int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not append value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Appends a value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static void AddTo<T>(this System.Enum type, ref T value) 
    { 
     try 
     { 
      value = (T)(object)(((int)(object)type | (int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not append value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Removes the value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static T Remove<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (T)(object)(((int)(object)type & ~(int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not remove value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Removes the value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static void RemoveFrom<T>(this System.Enum type, ref T value) 
    { 
     try 
     { 
      value = (T)(object)(((int)(object)type & ~(int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not remove value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 
} 
17
bool IsCDF(MyEnum enumValue) 
{ 
    return new[]{MyEnum.C, MyEnum.D, MyEnum.F}.Contains(enumValue); 
} 
Powiązane problemy