在我的生活中,我不记得如何设置,删除,切换或测试位域中的位。要么我不确定,要么我把它们弄混了,因为我很少需要它们。所以有一个“bit-cheat-sheet”会很好。
例如:
flags = flags | FlagsEnum.Bit4; // Set bit 4.
or
if ((flags & FlagsEnum.Bit4)) == FlagsEnum.Bit4) // Is there a less verbose way?
你能给出所有其他常见操作的例子吗,最好是在c#语法中使用[Flags]枚举?
为了获得最佳性能和零垃圾,请使用以下代码:
using System;
using T = MyNamespace.MyFlags;
namespace MyNamespace
{
[Flags]
public enum MyFlags
{
None = 0,
Flag1 = 1,
Flag2 = 2
}
static class MyFlagsEx
{
public static bool Has(this T type, T value)
{
return (type & value) == value;
}
public static bool Is(this T type, T value)
{
return type == value;
}
public static T Add(this T type, T value)
{
return type | value;
}
public static T Remove(this T type, T value)
{
return type & ~value;
}
}
}
c++语法,假设第0位是LSB,假设flags是unsigned long:
检查是否设置:
flags & (1UL << (bit to test# - 1))
检查是否未设置:
invert test !(flag & (...))
Set:
flag |= (1UL << (bit to set# - 1))
明确:
flag &= ~(1UL << (bit to clear# - 1))
切换:
flag ^= (1UL << (bit to set# - 1))
@Drew
注意,除了在最简单的情况下,Enum。与手动编写代码相比,HasFlag会带来严重的性能损失。考虑下面的代码:
[Flags]
public enum TestFlags
{
One = 1,
Two = 2,
Three = 4,
Four = 8,
Five = 16,
Six = 32,
Seven = 64,
Eight = 128,
Nine = 256,
Ten = 512
}
class Program
{
static void Main(string[] args)
{
TestFlags f = TestFlags.Five; /* or any other enum */
bool result = false;
Stopwatch s = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
result |= f.HasFlag(TestFlags.Three);
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds); // *4793 ms*
s.Restart();
for (int i = 0; i < 10000000; i++)
{
result |= (f & TestFlags.Three) != 0;
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds); // *27 ms*
Console.ReadLine();
}
}
在1000万次迭代中,HasFlags扩展方法花费了4793毫秒,而标准的逐位实现只需要27毫秒。
为了获得最佳性能和零垃圾,请使用以下代码:
using System;
using T = MyNamespace.MyFlags;
namespace MyNamespace
{
[Flags]
public enum MyFlags
{
None = 0,
Flag1 = 1,
Flag2 = 2
}
static class MyFlagsEx
{
public static bool Has(this T type, T value)
{
return (type & value) == value;
}
public static bool Is(this T type, T value)
{
return type == value;
}
public static T Add(this T type, T value)
{
return type | value;
}
public static T Remove(this T type, T value)
{
return type & ~value;
}
}
}