关于 Enum Flag 的最大尺寸

About the maximum size of Enum Flag

我有一个问题。

目前正在研究Enum函数中的Flag。 然后我想知道,我可以指定为枚举标志的最大大小是多少?

我目前正在标记如下标志。

A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
ZZZ = 1 << MaxSize(?)

我很好奇最大尺寸的值。

感谢阅读,由于是翻译,可能有语法错误。 :-)

以下是我的随机想法,排名不分先后:


  • 在 .NET 中,enum 类型本质上是枚举的 底层类型 的一组命名常量。
    • 尽管 C# 编译器不允许枚举值与其底层类型0除外)之间的隐式转换。
  • .NET 公共语言基础结构规范中对此进行了记录:ECMA-335, 5th edition (2010), page 34
  • 在 C# 中,enum 可以使用任何 .NET 的内置整数类型作为 底层类型(从 2021 年的 .NET 5 开始,我们仍然限制在与 2001 年相同的 8 个整数字节,但我们 可能 最终得到一个真正的 Int128,但这还需要几年的时间):
    • ByteSByte(1 个八位字节:8 位,值分别为 0-255-128127)。
    • UInt16Int16(2 字节又名 2 个八位字节:16 位,值分别为 0-65535-3276832767)。
    • UInt32Int32(4 字节,32 位等)。
    • UInt64Int64(8 字节,64 位等)。
    • (我相信 .NET 规范在技术上 允许 Boolean/bool 用作枚举基础类型,但 C# 允许不允许这样做)。

很明显,Int64UInt64(对 shift 键过敏的人又称为 longulong)提供最广泛的“space" 对于位值:毕竟有 64 位可供使用 - 而其他 底层类型 仅授予您 32、16 或区区 8 位。


enum 中的成员数量没有限制,但显然 底层类型 较小的枚举会比更大的更快地耗尽其可能值集类型并最终会重复自己。

enum 类型可以有多个名称不同但共享相同整数值的成员,但是在内部 CLR 无法区分彼此。


what is the maximum size that I can designate as Enum Flag?

如果您指的是 基础类型 那么直接的答案是 Int64 (long) 或 UInt64 ( ulong).

如果您询问的是枚举成员可以拥有的最大 ,那么那将是 YourUnderlyingType.MaxValue,例如:

enum IntSizedEnum : Int32
{
    LargestValue = Int32.MaxValue
}

enum BiggerEnum : UInt64
{
    EvenLargerLargestValue = UInt64.MaxValue
}

如果您询问设置的位数,那么如果您使用 Int64UInt64,您可以获得 64 位或单独的标志 - 甚至可以在位上定义它们 -以位为基础的位文字,例如:

enum BiggerEnum : UInt64
{
    All64Bits = 0b_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111
}

有了旗帜,你可以变得有点疯狂:

[Flags]
enum BiggerEnum : UInt64
{
    FlagsCombination = Bit_32 | Bit_33 | Bit_34,

    Bit_0  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001,
    Bit_1  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010,
    Bit_2  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000100,
    Bit_3  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00001000,
    Bit_4  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00010000,
    Bit_5  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00100000,
    Bit_6  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01000000,
    Bit_7  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10000000,
    Bit_8  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000000,
    Bit_9  = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000010_00000000,
    Bit_10 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000100_00000000,
    Bit_11 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00001000_00000000,
    Bit_12 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00010000_00000000,
    Bit_13 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00100000_00000000,
    Bit_14 = 0b00000000_00000000_00000000_00000000_00000000_00000000_01000000_00000000,
    Bit_15 = 0b00000000_00000000_00000000_00000000_00000000_00000000_10000000_00000000,
    Bit_16 = 0b00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000,
    Bit_17 = 0b00000000_00000000_00000000_00000000_00000000_00000010_00000000_00000000,
    Bit_18 = 0b00000000_00000000_00000000_00000000_00000000_00000100_00000000_00000000,
    Bit_19 = 0b00000000_00000000_00000000_00000000_00000000_00001000_00000000_00000000,
    Bit_20 = 0b00000000_00000000_00000000_00000000_00000000_00010000_00000000_00000000,
    Bit_21 = 0b00000000_00000000_00000000_00000000_00000000_00100000_00000000_00000000,
    Bit_22 = 0b00000000_00000000_00000000_00000000_00000000_01000000_00000000_00000000,
    Bit_23 = 0b00000000_00000000_00000000_00000000_00000000_10000000_00000000_00000000,
    Bit_24 = 0b00000000_00000000_00000000_00000000_00000001_00000000_00000000_00000000,
    Bit_25 = 0b00000000_00000000_00000000_00000000_00000010_00000000_00000000_00000000,
    Bit_26 = 0b00000000_00000000_00000000_00000000_00000100_00000000_00000000_00000000,
    Bit_27 = 0b00000000_00000000_00000000_00000000_00001000_00000000_00000000_00000000,
    Bit_28 = 0b00000000_00000000_00000000_00000000_00010000_00000000_00000000_00000000,
    Bit_29 = 0b00000000_00000000_00000000_00000000_00100000_00000000_00000000_00000000,
    Bit_30 = 0b00000000_00000000_00000000_00000000_01000000_00000000_00000000_00000000,
    Bit_31 = 0b00000000_00000000_00000000_00000000_10000000_00000000_00000000_00000000,
    Bit_32 = 0b00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000,
    Bit_33 = 0b00000000_00000000_00000000_00000010_00000000_00000000_00000000_00000000,
    Bit_34 = 0b00000000_00000000_00000000_00000100_00000000_00000000_00000000_00000000,
    Bit_35 = 0b00000000_00000000_00000000_00001000_00000000_00000000_00000000_00000000,
    Bit_36 = 0b00000000_00000000_00000000_00010000_00000000_00000000_00000000_00000000,
    Bit_37 = 0b00000000_00000000_00000000_00100000_00000000_00000000_00000000_00000000,
    Bit_38 = 0b00000000_00000000_00000000_01000000_00000000_00000000_00000000_00000000,
    Bit_39 = 0b00000000_00000000_00000000_10000000_00000000_00000000_00000000_00000000,
    Bit_40 = 0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000,
    Bit_41 = 0b00000000_00000000_00000010_00000000_00000000_00000000_00000000_00000000,
    Bit_42 = 0b00000000_00000000_00000100_00000000_00000000_00000000_00000000_00000000,
    Bit_43 = 0b00000000_00000000_00001000_00000000_00000000_00000000_00000000_00000000,
    Bit_44 = 0b00000000_00000000_00010000_00000000_00000000_00000000_00000000_00000000,
    Bit_45 = 0b00000000_00000000_00100000_00000000_00000000_00000000_00000000_00000000,
    Bit_46 = 0b00000000_00000000_01000000_00000000_00000000_00000000_00000000_00000000,
    Bit_47 = 0b00000000_00000000_10000000_00000000_00000000_00000000_00000000_00000000,
    Bit_48 = 0b00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_49 = 0b00000000_00000010_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_50 = 0b00000000_00000100_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_51 = 0b00000000_00001000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_52 = 0b00000000_00010000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_53 = 0b00000000_00100000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_54 = 0b00000000_01000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_55 = 0b00000000_10000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_56 = 0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_57 = 0b00000010_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_58 = 0b00000100_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_59 = 0b00001000_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_60 = 0b00010000_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_61 = 0b00100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_62 = 0b01000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000,
    Bit_63 = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000
}
// Usage:
BiggerEnum value = default;
value |= BiggerEnum.Bit_32 | BiggerEnum.Bit_33 | BiggerEnum.Bit_34;

Console.WriteLine( value == BiggerEnum.FlagsCombination ); // true
Console.WriteLine( value ); // 30064771072

...但你真的不应该那样做。

按照您希望通过位移使用它的方式,它将是

1 << 31

也就是

-2147483648

而且 int 恰好有 32 位,所以如果你这样做

1 << 32

意味着你取值 1

00000000 00000000 00000000 00000001

现在将所有位向左移动 32 次,结果又是 1

1 << 0

将底层枚举类型更改为例如ulong。至少不使用位移运算符,因为位移运算符总是只能位移 int 值(参见 here)。


如果你真的想发疯,看看手动您实际上可以扩展标志以使用底层类型ulong并具有最多64个值。