枚举上最常见的C#按位运算

时间:2020-03-06 14:22:01  来源:igfitidea点击:

为了我的一生,我不记得如何在位域中进行设置,删除,切换或者测试。我不确定还是将它们混在一起,因为我很少需要这些。因此,拥有一个"位备忘单"将是不错的选择。

例如:

flags = flags | FlagsEnum.Bit4;  // Set bit 4.

或者

if ((flags & FlagsEnum.Bit4)) == FlagsEnum.Bit4) // Is there a less verbose way?

我们能否举例说明所有其他常见操作,最好使用[Flags]枚举在Csyntax中进行?

解决方案

C ++操作是:&| ^〜(用于and,or,xor和非按位运算)。还感兴趣的是>>和<<,它们是位移位操作。

因此,要测试是否在标志中进行了设置,可以使用:
if(flags&8)//测试第4位是否已设置

习惯用法是使用按位或者等号运算符设置位:

flags |= 0x04;

为了清楚一点,习惯用法是按位取反:

flags &= ~0x04;

有时我们有一个偏移量来标识位,然后习惯用法是将这些与左移结合使用:

flags |= 1 << offset;
flags &= ~(1 << offset);

C ++语法,假设第0位为LSB,并假设标志为无符号长整数:

检查是否设置:

flags & (1UL << (bit to test# - 1))

检查是否设置:

invert test !(flag & (...))

放:

flag |= (1UL << (bit to set# - 1))

清除:

flag &= ~(1UL << (bit to clear# - 1))

切换:

flag ^= (1UL << (bit to set# - 1))

要测试一下,我们可以执行以下操作:
(假设标志是一个32位数字)

测试位:

if((flags & 0x08) == 0x08)

(如果设置了位4,则它为true)
向后切换(1 0或者0 1):

flags = flags ^ 0x08;

将位4重置为零:

flags = flags & 0xFFFFFF7F;

我对这些扩展做了更多的工作,我们可以在这里找到代码

我写了一些扩展方法,这些方法扩展了我经常使用的System.Enum。

namespace Enum.Extensions {

    public static class EnumerationExtensions {

        public static bool Has<T>(this System.Enum type, T value) {
            try {
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            } 
            catch {
                return false;
            }
        }

        public static bool Is<T>(this System.Enum type, T value) {
            try {
                return (int)(object)type == (int)(object)value;
            }
            catch {
                return false;
            }    
        }

        public static T Add<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type | (int)(object)value));
            }
            catch(Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not append value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }    
        }

        public static T Remove<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type & ~(int)(object)value));
            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not remove value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }  
        }

    }
}

然后像下面这样使用

SomeType value = SomeType.Grapes;
bool isGrapes = value.Is(SomeType.Grapes); //true
bool hasGrapes = value.Has(SomeType.Grapes); //true

value = value.Add(SomeType.Oranges);
value = value.Add(SomeType.Apples);
value = value.Remove(SomeType.Grapes);

bool hasOranges = value.Has(SomeType.Oranges); //true
bool isApples = value.Is(SomeType.Apples); //false
bool hasGrapes = value.Has(SomeType.Grapes); //false