【问题标题】:How should I represent a value of None when a [Flags] enum type doesn't define it?当 [Flags] 枚举类型未定义它时,我应该如何表示 None 的值?
【发布时间】:2015-05-18 18:25:49
【问题描述】:

今天在使用 XNA 时,我注意到使用 [Flags] 的枚举类型之一没有 None = 0 值:

[Flags]
public enum Buttons
{
    DPadUp = 1,
    DPadDown = 2,
    DPadLeft = 4,
    DPadRight = 8,
    Start = 16,
    Back = 32,
    LeftStick = 64,
    RightStick = 128,
    LeftShoulder = 256,
    RightShoulder = 512,
    BigButton = 2048,
    A = 4096,
    B = 8192,
    X = 16384,
    Y = 32768,
    LeftThumbstickLeft = 2097152,
    RightTrigger = 4194304,
    LeftTrigger = 8388608,
    RightThumbstickUp = 16777216,
    RightThumbstickDown = 33554432,
    RightThumbstickRight = 67108864,
    RightThumbstickLeft = 134217728,
    LeftThumbstickUp = 268435456,
    LeftThumbstickDown = 536870912,
    LeftThumbstickRight = 1073741824,
}

根据 MSDN 关于proper use of the [Flags] attribute

将标志枚举的零值命名为None。对于标志枚举,该值必须始终表示所有标志都已清除。

如果我想指示一个没有按下按钮的值,使用值 0 并将其强制转换为 Buttons 会违背枚举类型的意图吗?根据设计指南,它应该有这个值,但它没有。

【问题讨论】:

  • 枚举用于 GamePadState.IsButtonUp/Down() 方法。用这些方法询问是否没有按钮是没有意义的。所以包含 None 是没有意义的。您无法更改类型,它被烘焙到 XNA 中,但由于 0 始终是枚举的有效值,您始终可以使用 default(Buttons)。
  • 我认为是这样的。我不喜欢针对每种输入类型如何以不同方式处理按钮轮询(鼠标按钮甚至没有自己的枚举类型,这与键盘和游戏手柄不同)。我当前的项目正在围绕不同类型的输入创建一个通用包装类,例如保存当前和以前的KeyboardState,以便我可以轻松地轮询一个键或按钮是刚刚按下还是释放。因此,我可以让客户端轮询我创建的 IsPressed() 方法或订阅事件,因此这是使 GamePadEventArgs 包含 Buttons 值的结果。

标签: c# enum-flags


【解决方案1】:

是的。因为它是一个Flags 枚举,所以没有设置的可能值的状态将是(Buttons)0(或者default(Buttons),如果您希望以某种方式直接在代码中反映类型),该类型的设计者是否为其分配了名称。

考虑如果我们可以通过Buttons.A & ~Buttons.A 表达“没有按下不是A 按钮并且A 按钮也没有按下的按钮”,结果将是(Buttons)0。 “没有按下按钮”状态已经是0

(我能想到的省略None 的一个理由是,您打算在None 是按下的值的情况下从不使用类型。例如,您仅将其用于以下代码对按下的按钮做出反应,因此 None 永远不会出现。即使这样,人们也可以发现在代码中使用 None/0 值很有用,但这可能意味着不命名它更合理)。

【讨论】:

  • 你甚至不需要(Buttons)0中的演员:D
  • @Leppie:没错,但它使 IMO 的意图更加清晰。
  • @leppie 是的。在我的回答中,我什至没有考虑演员阵容,而是如何表达0 的类型是Buttons
【解决方案2】:

没有上下文很难说。如果您想表示按下或不按下某物的状态,在这种情况下我会选择Nullable<Buttons>

class Input
{
    ...
    private Buttons? _buttons;
    ...
}

它还可以保护您免受 Buttons 的未来版本的影响,其中 0可能被添加以表示“无”以外的其他内容。是的,不太可能,但并非完全不可能。

【讨论】:

    猜你喜欢
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 2012-03-10
    相关资源
    最近更新 更多