FlagsAttribute枚举在C#中的行为是什么
本文关键字:是什么 枚举 FlagsAttribute | 更新日期: 2023-09-27 18:25:20
我有以下代码:
namespace ConsoleApplication1
{
internal class Program
{
[FlagsAttribute]
private enum RenderType
{
DataUri = 0,
GZip = 1,
ContentPage = 2,
ViewPage = 4,
HomePage = 8
}
private static void Main()
{
// 4.
// Set a new enum in three statements.
RenderType type2 = RenderType.ViewPage;
// 5.
// See if the enum contains this flag.
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.DataUri) == RenderType.DataUri)
{
Console.WriteLine("DataUri");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
}
}
每当我运行此代码时,它都会给我一个输出:
查看页面DataUri
我只想要ViewPage的输出,因为我正在给我的枚举ViewPage赋值。
有人能帮我吗?为什么会这样?我的枚举声明或代码有什么问题吗?
您已经声明DataUri = 0
所以
(type2 & RenderType.DataUri) == RenderType.DataUri
将始终评估为CCD_ 2。
从1开始您的有效枚举值。
任何按位加零的数字都是零。以1开始枚举,然后增加2的幂。此外,更好地理解二进制数和逐位运算符将有助于
DataUri为0:因此x & DataUri
始终为零!试试这个:
if(type2 != RenderType.DataUri) {
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
使用位掩码时,值0通常表示NONE标志。所以你应该从1开始计数到2^n,这是一个更好的练习IMHO:
[FlagsAttribute]
private enum RenderType
{
None = 0,
DataUri = 1,
GZip = 2,
ContentPage = 4,
ViewPage = 8,
HomePage = 16
}
因为x & 0
总是等于零。
不要将0(零)指定为[Flags]枚举的可能值。请记住,[Flags]枚举是一个位字段,零值并不会真正映射到任何字段中,因此它总是返回true。
根据Krzysztof Cwalina的框架设计指南:
Avoid using flag enum values normal members that are negative or zero.
负值会在按位操作中产生意外/令人困惑的结果。枚举值为零会给和操作等带来问题:
原因是RenderType.DataUri
的值为0
。
您的代码所做的是通过在type2
和它测试的枚举成员之间执行按位and
操作来检查type2
枚举变量的按位配置。
在您的示例中,type2
的值为4,这是二进制的0100
(最多为枚举所需的4位)。当您测试RenderType.GZip
(0001
)时,它会进行以下计算:
0100 & 0001 = 0000
由于0000 != 0001
,所以在type2
中不设置RenderType.GZip
比特。但是,0100 & 0000
始终是0000
,所以在检查RenderType.DataUri
时,您总是会得到true。
本质上,true
0枚举为其每个成员使用不同的位,但由于0
不表示整数中的位,因此它的行为不会像预期的那样。
正如其他人所说,由于二进制算法的工作原理,您应该在1处启动Flags枚举。我只想补充一点,你可能想使用HasFlag方法(我相信在.NET 4.0中是新的)来检查标志:
if(type2.HasFlag(RenderType.ViewPage))
{
...
}
http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx