Sco*_*ner 6 c# enums flags design-patterns
我在C#中创建了一个标志枚举,类似于以下内容:
[Flags]
public enum DriversLicenseFlags
{
None = 0,
Suspended = 1 << 1,
Revoked = 1 << 2,
Restored = 1 << 3,
SuspendedAndRestored = Suspended | Restored,
RevokedAndRestored = Revoked | Restored,
}
Run Code Online (Sandbox Code Playgroud)
关于我的意图的一些注意事项:
Suspended并且Revoked是可以但不一定导致恢复的独特状态.Restored应该只有在用户已经Suspended或Revoked(或两者都有)的情况下才有可能.重要的是要具体跟踪哪个事件是恢复的前兆.Suspended和Revoked(和Restored)另外,我试图坚持在MSDN的Designing Flags Enumerations中提出的建议.特别是:
SuspendedAndRestored并且RevokedAndRestored两者都很常见.Restored除非至少有一个是无效的Suspended,并Revoked设置.理想情况下,我希望Restored在内部使用的枚举中存在一个值,但只能通过某些有效组合公开设置.不幸的是,internal它不是枚举值的有效修饰符.
我想过几个选择,但每个似乎都有缺点:
保留Restored作为公共值,请注意注释中的限制,并对公共API上的无效组合进行前置条件检查.
这可行,并且很可能是我将采用的解决方案.但是,似乎他们应该是一个更清洁的解决方案.
使用这里描述的增强的类似java的枚举并定义Restored为internal static.
这也可行,但感觉有点矫枉过正,因为此时我不需要任何其他功能.
不要定义Restored为值,而是保留OR的值,并检查使用方法中的值.即:
internal const int RestoredFlag = 1 << 3;
[Flags]
public enum DriversLicenseFlags
{
None = 0,
Suspended = 1 << 1,
Revoked = 1 << 2,
SuspendedAndRestored = Suspended | RestoredFlag,
RevokedAndRestored = Revoked | RestoredFlag,
}
Run Code Online (Sandbox Code Playgroud)无论是如何定义以及如何在内部使用它,这都让我觉得很烦.
为什么要Flags专门使用呢?这不正是您所追求的吗?
public enum DriversLicenseStatus
{
None = 0,
Suspended,
Revoked,
SuspendedAndRestored,
RevokedAndRestored,
}
Run Code Online (Sandbox Code Playgroud)
确保仅从属性的属性设置器内进行“有效”转换当然很容易DriversLicenseStatus。
如果出于某种原因您确实想Flags在内部使用,那么您可以定义一个单独的对象private enum DriversLicenseStatusFlags并从中转换为仅DriversLicenseStatus在公共接口中公开值。
另一个值得考虑的选择是将枚举分为两个值:
bool IsActive;
enum InactiveReason {
None = 0,
Suspended,
Revoked,
}
Run Code Online (Sandbox Code Playgroud)
“AndRestored”案例是带有IsActive == true和 的案例InactiveReason != InactiveReason.None。
我的明显印象是你在这里过度设计了。:)