我正在使用带有flags属性的枚举作为跟踪状态的方法。
以下是一个例子:
Created = 1
Completed = 2
Dispatched = 4
没有写太严格的东西(如果检查这个,那么,如果检查一下,这样做)我希望能够找到已经设置的最高标志,在这个例子中:
Item.Status = Status.Created | Status.Completed
神话方法将返回2 - 完成后设置的值为最高值。
GetMaxSetFlagValue(Item.Status) // returns 2
我发现了围绕实际枚举的问题,而不是使用标志的值。我很确定这可以用Linq实现......?
答案 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;
}