简要介绍C#位域(flags)的相关知识+各种整理!

之一:简要介绍C#位域(flags)的相关知识

作者:shelley 2018-08-12 来源:51CTO

C#位域主要用于.net里面对于某一个事物有多种混合状态时使用,单一的枚举更的在事物只具有单一属性时使用。为了更好的实现混合状态,我们可以在枚举加上C#位域标签。下面的这个就是我们在本文中用到的实例:

[Flags]
public enum Week
{
[Description("星期一")]
Monday = 1 < < 0,
[Description("星期二")]
Tuesday = 1 < < 1,
[Description("星期三")]
Wednesday = 1 < < 2,
[Description("星期四")]
Tursday = 1 < < 3,
[Description("星期五")]
Friday = 1 < < 4,
[Description("星期六")]
Saturday = 1 < < 5,
[Description("星期日")]
Sunday = 1 < < 6
}
位域支持的运算符

  1. “|”:表示两边求并集(元素相加,相同元素只出现一次)

Week week = Week.Tuesday | Week.Monday | Week.Monday;
MessageBox.Show(Convert.ToString(week));
这段代码的结果就是 Monday,Tuesday

  1. “&”:表示两边是否其中一个是另外一个的子集,如果是返回子集,否则返回0(如果其中一个包含另外一个,返回被包含的,否则返回0)

week = Week.Monday & week;
MessageBox.Show(week.ToString());与week = week & Week.Monday;
MessageBox.Show(week.ToString());
上面这两段代码的结果是相同的,如果week的初始值为:Monday,Tuesday,返回的结果为:Monday

3.“^”:表示从两者的并集中去除两者的交集(把两个的元素合并到一起,如果两个中有公共元素,要将这个公共元素从合并的结果中去除)

week = (Week.Monday | Week.Wednesday)^ (Week.Tuesday | Week.Monday);
MessageBox.Show(week.ToString());
week = (Week.Monday | Week.Wednesday) ^ (Week.Tuesday | Week.Sunday);
MessageBox.Show(week.ToString());
上面两个返回的结果应该为:Tuesday,Wednesday 和 Monday,Tuesday,Wednesday,Sunday

4.“~”:表示取反,返回的结果我还不知道应该是什么,以后再查一下。用法主要和“&”一起使用,例如:去除其中的某个元素

week = Week.Tuesday | Week.Monday | Week.Wednesday;
week = week &(~Week.Monday);
MessageBox.Show(week.ToString());
上面返回的结果为:Tuesday,Wednesday

正逆转化

上面的内容存在数据库时我们可能为了简单只存取数字即可,例如:1表示Monday,3表示Monday,Tuesday。我们可以根据数据库里面的值方便获取存储的内容,代码如下:

week = Week.Monday | Week.Tuesday;
MessageBox.Show(Convert.ToString((int)week));
week = (Week)Enum.Parse(typeof(Week), "10");
MessageBox.Show(week.ToString());
返回的结果为:3 和 Tuesday,Tursday

获取Description标签内容

我们既然可以给里面的值加上Description,就可以在程序中获取到这个内容,至于用途,大家自己看吧,东西摆出来,大家自己随便怎么用,下面的代码是从网上找到的,内容如下:

/// < summary>
/// 从枚举类型和它的特性读出并返回一个键值对
/// < /summary>
/// < param name="enumType">Type,该参数的格式为typeof(需要读的枚举类型)< /param>
/// < returns>键值对< /returns>
public static NameValueCollection GetNVCFromEnumValue(Type enumType)
{
NameValueCollection nvc = new NameValueCollection();
Type typeDescription = typeof(DescriptionAttribute);
System.Reflection.FieldInfo[] fields = enumType.GetFields();
string strText = string.Empty;
string strValue = string.Empty;
foreach (FieldInfo field in fields)
{
if (field.FieldType.IsEnum)
{
strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
object[] arr = field.GetCustomAttributes(typeDescription, true);
if (arr.Length > 0)
{
DescriptionAttribute aa = (DescriptionAttribute)arr[0];
strText = aa.Description;
}
else
{
strText = field.Name;
}
nvc.Add(strText, strValue);
}
}
return nvc;
}
C#位域(flags)的相关知识就介绍到这里。

本文原作者shelley,原文链接http://developer.51cto.com/art/200909/148735.htm

之二:C# 特性(Attribute)之Flag特性

本文参考自C# 位域[flags],纯属读书笔记,加深记忆

[Flags]的微软解释是“指示可以将枚举作为位域(即一组标志)处理。”其实就是在编写枚举类型时,上面附上Flags特性后,用该枚举变量是既可以象整数一样进行按位的“|”或者按位的“&”操作了。
另外一个是在引用COM组件时使用,我没有用过,你可以查看MSDN

这种用处很大,比如权限、执行状态等,都可以用一个int型保存到数据库中,C#中使用枚举可以处理这个问题。

.Net中的枚举一般有两种用法

(1)、表示唯一的元素序列,列入一周天里面的各天

(2)、表示多种的复合状态,这个时候一般需要为枚举加上[Flags]特性为标记

下面通过代码演示[Flags]特性的作用

1、不加[Flag]特性的代码

复制代码

    public enum Permission
    {
        create = 1,
        read = 2,
        update = 4,
        delete = 8,
    }

    static void Main(string[] args)
    {
        Permission permission = Permission.create | Permission.read | Permission.update | Permission.delete;
        Console.WriteLine("1、枚举创建,并赋值……");
        Console.WriteLine(permission.ToString());
        Console.WriteLine((int)permission);
    }

复制代码
输出:

2、加[Flag]特性的代码

复制代码

    **[Flags]
    public enum Permission
    {
        create = 1,
        read = 2,
        update = 4,
        delete = 8,
    }**

    static void Main(string[] args)
    {
        Permission permission = Permission.create | Permission.read | Permission.update | Permission.delete;
        Console.WriteLine("1、枚举创建,并赋值……");
        Console.WriteLine(permission.ToString());
        Console.WriteLine((int)permission);
    }

复制代码
输出:

3、分析上面的代码,发现加上[Flags]特性之后,对于枚举的追加操作,没加特性的只是单纯的从值上的相加,而加了特性的则是枚举上的相加。这也导致了create=1,read=2,update=4,delete=8的原因,因为两个状态的值相加不能等于其中任何一个的值,如果相等的话,那么[Flag]也就失去了使用它的意义(因为给一个用户赋予进行read和delete操作的权限,如果两个相加的值等于update,那不乱套了么,所以这里两个状态的值相加不能等于其中任何一个的值)。当然这里如果加一个可读可删的权限,那么就可以这样写了:readAndDelete=10。是不是很灵活!!!

这种用处很大,比如权限、执行状态等,都可以用一个int型保存到数据库中,C#中使用枚举可以处理这个问题。

================================
以上都有不足,这里增加了一些,声明的方式:
1)从零开始。 零会屏蔽以上所有的项目,怎么运算都是0。
[Flags]
internal enum HttpHeaderType
{
** Unspecified = 0,

Request = 1,**
Response = 1 << 1,
Restricted = 1 << 2,
MultiValue = 1 << 3,
MultiValueInRequest = 1 << 4,
MultiValueInResponse = 1 << 5

}
//如何处理判断逻辑。
if ( value ) {

                flags |= (int)GeneralBitFlags.UnicodeText;//增加
            }
            else {
                flags &= ~(int)GeneralBitFlags.UnicodeText;//减少
            }
            
            判断====>>>
            **Short localFlags=1;
            if ( (localFlags **& ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) {

![screenshot]
(
h public enum InstalledHook

{
    /// <summary>
    /// 没有安装钩子
    /// </summary>
    None = 0,

    /// <summary>
    /// 安装了WH_GETMESSAGE 钩子
    /// </summary>
    GetMessage = 1,

    /// <summary>
    /// 安装了WH_CALLWNDPROC钩子
    /// </summary>
    CallWndProc = GetMessage << 1,

    /// <summary>
    /// 安装了WH_MSGFILTER钩子
    /// </summary>
    SystemMessage = CallWndProc << 1,
    All = GetMessage | CallWndProc | SystemMessage,
}

//16进制的声明
public enum SPIActions

{
    SPI_GETBEEP                         = 0x0001,
    SPI_SETBEEP                         = 0x0002,
    SPI_GETMOUSE                        = 0x0003,
    SPI_SETMOUSE                        = 0x0004,
    SPI_GETBORDER                       = 0x0005,
    SPI_SETBORDER                       = 0x0006,
    SPI_GETKEYBOARDSPEED                = 0x000A,
    SPI_SETKEYBOARDSPEED                = 0x000B,
    SPI_LANGDRIVER                      = 0x000C,
    SPI_ICONHORIZONTALSPACING           = 0x000D,
    SPI_GETSCREENSAVETIMEOUT            = 0x000E,
    SPI_SETSCREENSAVETIMEOUT            = 0x000F,
    SPI_GETSCREENSAVEACTIVE             = 0x0010,
    SPI_SETSCREENSAVEACTIVE             = 0x0011,
    SPI_GETGRIDGRANULARITY              = 0x0012,

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章