空旗是坏习惯吗?
Is an empty flag a bad habit?
几天前我遇到了一个非常愚蠢的错误。这是由我从第三方库获得的枚举引起的:
[Flags]
public enum MyStatus
{
OKResponse = 0,
ResponseTooBig = 1,
ErrorMessage = 2,
NoResponse = 4,
...
}
我习惯这样检查标志:
if ((status & MyStatus.OKResponse) != 0) {...}
但它不适用于 MyStatus.OKResponse
,因为它是零。它根本不是一面旗帜,它是所有旗帜的缺席。当然,当我发现这个错误时,我意识到 OKResponse
是唯一的非错误状态,所以它实际上意味着 "no errors, no flags"。但是,我真的不觉得很明显。
将 0 定义为 flags 枚举中的值之一是个坏习惯吗?推荐的方法是什么?检查标志的最佳方法是什么,它也适用于 "no flags" 标志?
Is it a bad habit defining 0 as one of values in flags enum?
不,相反,正如评论所说,通常使用 0
作为给定标志的值,如果没有分配不同的值,这就是枚举的默认值第一个给定的值。正如其他人在评论中所说,使用 Enum.None
作为枚举的第一个值也很常见,这让阅读代码的其他人更清楚你的意图。
What is the recommended way?
没有一种方法可以做到,但我通常喜欢使用简洁的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)}");
}
虽然在你的枚举中实际定义一个 0
值是个好主意,但它代表 OK
是一个非常糟糕的主意,因为 0
是默认值并且它是唯一可以隐式转换为枚举的特殊整数,因此它很容易潜入:
MyStatus status = 0;
所以 0
值的实际定义不是问题,但是让它代表 Flags
枚举的 None
或 [=18] 是个好主意=] 普通枚举的值。
此外,Flags
当成员可以组合时应该使用枚举,但从你的例子来看它们似乎是互斥的。
所以我想说枚举设计得很糟糕,因为事实上,任何响应都有一个 OK 标志,这肯定是 Flags
枚举的一个错误,如果你不能改变定义,唯一的方法是显式检查状态是否等于 OKResponse
:
if (status == MyStatus.OKResponse)
几天前我遇到了一个非常愚蠢的错误。这是由我从第三方库获得的枚举引起的:
[Flags]
public enum MyStatus
{
OKResponse = 0,
ResponseTooBig = 1,
ErrorMessage = 2,
NoResponse = 4,
...
}
我习惯这样检查标志:
if ((status & MyStatus.OKResponse) != 0) {...}
但它不适用于 MyStatus.OKResponse
,因为它是零。它根本不是一面旗帜,它是所有旗帜的缺席。当然,当我发现这个错误时,我意识到 OKResponse
是唯一的非错误状态,所以它实际上意味着 "no errors, no flags"。但是,我真的不觉得很明显。
将 0 定义为 flags 枚举中的值之一是个坏习惯吗?推荐的方法是什么?检查标志的最佳方法是什么,它也适用于 "no flags" 标志?
Is it a bad habit defining 0 as one of values in flags enum?
不,相反,正如评论所说,通常使用 0
作为给定标志的值,如果没有分配不同的值,这就是枚举的默认值第一个给定的值。正如其他人在评论中所说,使用 Enum.None
作为枚举的第一个值也很常见,这让阅读代码的其他人更清楚你的意图。
What is the recommended way?
没有一种方法可以做到,但我通常喜欢使用简洁的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)}");
}
虽然在你的枚举中实际定义一个 0
值是个好主意,但它代表 OK
是一个非常糟糕的主意,因为 0
是默认值并且它是唯一可以隐式转换为枚举的特殊整数,因此它很容易潜入:
MyStatus status = 0;
所以 0
值的实际定义不是问题,但是让它代表 Flags
枚举的 None
或 [=18] 是个好主意=] 普通枚举的值。
此外,Flags
当成员可以组合时应该使用枚举,但从你的例子来看它们似乎是互斥的。
所以我想说枚举设计得很糟糕,因为事实上,任何响应都有一个 OK 标志,这肯定是 Flags
枚举的一个错误,如果你不能改变定义,唯一的方法是显式检查状态是否等于 OKResponse
:
if (status == MyStatus.OKResponse)