在枚举值中查找最高设置标志

我正在使用带有flags属性的枚举作为跟踪状态的方法。

一个例子如下:

Created = 1 Completed = 2 Dispatched = 4 

没有写任何过于严格的东西(如果检查这个,那么,如果检查,请执行此操作)我希望能够找到已在此示例中设置的最高标志:

 Item.Status = Status.Created | Status.Completed 

神秘的方法将返回2 – 完成后,标志设置为具有最高值。

 GetMaxSetFlagValue(Item.Status) // returns 2 

我发现了围绕实际枚举的问题,而不是使用标志的值。 我很确定这可以用Linq实现……?

像下面这样的东西应该工作:

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

如果T不是枚举类型,则该方法将失败,因此最好在方法的开头执行检查。 它也不适用于底层类型大于int (即long )的枚举。

这是我使用的扩展方法。 它会给你回复

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

输出:maxStatus =已完成

 public static class EnumExtensions { /// Enumerates get flags in this collection. /// /// The value. ///  /// /// An enumerator that allows foreach to be used to process get flags in this collection. public static IEnumerable GetFlags (this T value) where T : struct { return GetFlags (value, Enum.GetValues (value.GetType ()).Cast ().ToArray ()); } /// Enumerates get flags in this collection. /// ///  The value. ///  /// The values. ///  /// /// An enumerator that allows foreach to be used to process get flags in this collection. private static IEnumerable GetFlags (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 (); 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 (); if (Convert.ToUInt64 (value) != 0L) return results.Reverse (); if (bits == Convert.ToUInt64 (value) && values.Length > 0 && Convert.ToUInt64 (values [0]) == 0L) return values.Take (1); return Enumerable.Empty (); } } 

因为你可以来回使用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; }