2011-10-16 28 views
7

में उच्चतम सेट ध्वज ढूँढना मैं ट्रैकिंग स्थिति के तरीके के रूप में झंडे विशेषता के साथ एक enum का उपयोग कर रहा हूँ।एनम वैल्यू

Created = 1 
Completed = 2 
Dispatched = 4 

कुछ भी ज्यादा कठोर मैं उच्चतम ध्वज जो किया गया है खोजने के लिए सक्षम होना चाहते हैं (यदि जांच इस, कि, जाँच लें कि अगर, ऐसा क्यों करें) लेखन के बिना:

एक उदाहरण निम्नलिखित है इस उदाहरण में सेट करें:

Item.Status = Status.Created | Status.Completed 

पौराणिक विधि 2 वापस आ जाएगी - जैसा कि पूर्णतम मूल्य के साथ ध्वज सेट पूरा हो गया है।

GetMaxSetFlagValue(Item.Status) // returns 2 

मुझे ऐसे प्रश्न मिल गए हैं जो वास्तविक enum के आसपास घूमते हैं, केवल एक मूल्य जो झंडे का उपयोग नहीं करता है। मुझे यकीन है कि यह लिंक के साथ हासिल किया जा सकता है ...?

उत्तर

7

कुछ निम्नलिखित की तरह काम करना चाहिए:

static int GetMaxSetFlagValue<T>(T flags) where T : struct 
{ 
    int value = (int)Convert.ChangeType(flags, typeof(int)); 
    IEnumerable<int> setValues = Enum.GetValues(flags.GetType()).Cast<int>().Where(f => (f & value) == f); 
    return setValues.Any() ? setValues.Max() : 0; 
} 

विधि असफल हो जायेगी अगर टी एक enum प्रकार, नहीं है तो एक चेक अधिमानतः विधि की शुरुआत में किया जाना चाहिए। इसके अलावा यह int (यानी long) से बड़े अंतर्निहित प्रकार के साथ एक enum के लिए काम नहीं करेगा।

2

यह विस्तार विधि है जिसका मैं उपयोग करता हूं। यह आप enum दे देंगे वापस

var maxStatus = Item.Status.GetFlags().Max(); 

आउटपुट: maxStatus = पूरे

public static class EnumExtensions { 

    /// <summary>Enumerates get flags in this collection.</summary> 
    /// 
    /// <param name="value">The value. 
    /// </param> 
    /// 
    /// <returns>An enumerator that allows foreach to be used to process get flags in this collection.</returns> 
    public static IEnumerable<T> GetFlags<T> (this T value) where T : struct { 
     return GetFlags (value, Enum.GetValues (value.GetType()).Cast<T>().ToArray()); 
    } 

    /// <summary>Enumerates get flags in this collection.</summary> 
    /// 
    /// <param name="value"> The value. 
    /// </param> 
    /// <param name="values">The values. 
    /// </param> 
    /// 
    /// <returns>An enumerator that allows foreach to be used to process get flags in this collection.</returns> 
    private static IEnumerable<T> GetFlags<T> (T value, T [] values) where T : struct { 
     if (!typeof (T).IsEnum) { 
      throw new ArgumentException ("Type must be an enum."); 
     } 
     ulong bits = Convert.ToUInt64 (value); 
     var results = new List<T>(); 
     for (int i = values.Length - 1; i >= 0; i--) { 
      ulong mask = Convert.ToUInt64 (values [i]); 
      if (i == 0 && mask == 0L) 
       break; 
      if ((bits & mask) == mask) { 
       results.Add (values [i]); 
       bits -= mask; 
      } 
     } 
     if (bits != 0L) 
      return Enumerable.Empty<T>(); 
     if (Convert.ToUInt64 (value) != 0L) 
      return results.Reverse<T>(); 
     if (bits == Convert.ToUInt64 (value) && values.Length > 0 && Convert.ToUInt64 (values [0]) == 0L) 
      return values.Take (1); 
     return Enumerable.Empty<T>(); 
    } 
} 
0

आप आगे और पीछे डाली uint कर सकते हैं के रूप में, आप इस्तेमाल कर सकते हैं:

public uint LowestBit(uint x) 
{ 
    return ~(x&x-1)&x; 
} 
public uint HighestBit(uint x) 
{ 
    uint last = x; 
    while (x!=0) 
    { 
     last=x; 
     x&=x-1; 
    } 
    return last; 
} 
संबंधित मुद्दे