之一:简要介绍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
}
位域支持的运算符
- “|”:表示两边求并集(元素相加,相同元素只出现一次)
Week week = Week.Tuesday | Week.Monday | Week.Monday;
MessageBox.Show(Convert.ToString(week));
这段代码的结果就是 Monday,Tuesday
- “&”:表示两边是否其中一个是另外一个的子集,如果是返回子集,否则返回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,
}