空旗是坏习惯吗?

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)