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

时间:2011-10-16 11:51:53

标签: c# .net enums

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

以下是一个例子:

Created = 1
Completed = 2
Dispatched = 4

没有写太严格的东西(如果检查这个,那么,如果检查一下,这样做)我希望能够找到已经设置的最高标志,在这个例子中:

Item.Status = Status.Created | Status.Completed

神话方法将返回2 - 完成后设置的值为最高值。

GetMaxSetFlagValue(Item.Status) // returns 2

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

3 个答案:

答案 0 :(得分:8)

以下内容应该有效:

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;
}

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

答案 1 :(得分:2)

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

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> ();
    }
}

答案 2 :(得分: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;
}