几天前我遇到了一个非常愚蠢的错误。这是由我从第三方库获得的枚举引起的:
[Flags]
public enum MyStatus
{
OKResponse = 0,
ResponseTooBig = 1,
ErrorMessage = 2,
NoResponse = 4,
...
}
我习惯用这种方式检查标志:
if ((status & MyStatus.OKResponse) != 0) {...}
但它不适用于MyStatus.OKResponse
,因为它为零。它根本不是一面旗帜,它缺少所有旗帜。当然,当我发现错误时,我意识到OKResponse
是唯一的非错误状态,所以它实际上意味着“没有错误,没有标志”。但是,我真的不觉得这很明显。
将标志枚举为0中的值之一定义0是一个坏习惯吗?推荐的方式是什么?检查标志的最佳方法是什么,也可以使用“无标志”标志?
答案 0 :(得分:6)
将标志枚举中的值定义为0是一个坏习惯吗?
不,相反,正如评论所说,通常使用0
作为给定标志的值,如果没有为第一个标记分配不同的值,则枚举将默认为给定的价值。正如其他人在评论中所说的那样,使用Enum.None
作为枚举的第一个值也很常见,这使得您的意图更清晰,其他人也可以阅读代码。
推荐的方式是什么?
没有一种方法可以做到,但我通常喜欢使用简洁的Enum.HasFlag
方法:
void Main()
{
var status = MyStatus.ResponseTooBig | MyStatus.NoResponse;
if (status.Equals(MyStatus.OKResponse))
Console.WriteLine("Status is OKResponse");
else
Console.WriteLine($"Has NoResponse?: {status.HasFlag(MyStatus.NoResponse)}");
}
答案 1 :(得分:1)
虽然在枚举中实际定义0
值是个好主意,但它代表OK
是一个非常糟糕的主意,因为0
是默认值,它是唯一可以隐式转换为枚举的特殊整数,因此可以很容易地进行转换:
MyStatus status = 0;
因此,0
值的实际定义不是问题,但最好让它代表None
枚举Flags
或Invalid
正常枚举的价值。
此外,当成员可以合并时,应使用Flags
枚举,但从您的示例看,它们似乎是互斥的。
所以我说enum的设计很糟糕,因为实际上,任何响应都有一个OK标志,这肯定是Flags
枚举的错误,如果你不能改变定义,唯一的方法是明确检查状态是否等于OKResponse
:
if (status == MyStatus.OKResponse)