恐怕没有直接的 C# 等效于 C 风格的位域结构。
C# 能够在有限的范围内通过使用FieldOffset 属性来近似C 风格的联合。这些显式布局属性允许您指定准确且可能重叠的字段偏移量。不幸的是,这甚至不能让你走到一半:偏移量必须以 bytes 而不是位指定,并且在读取或写入重叠字段时不能强制指定特定宽度。
最接近原生支持位域的 C# 可能是基于标志的 enum 类型。如果您不需要超过 64 位,您可能会发现这已经足够了。首先根据适合所有标志的最小无符号类型声明enum:
[Flags]
public enum BitFields : byte {
None = 0,
VesselPresenceSw = 1 << 0,
DrawerPresenceSw = 1 << 1,
PumpState = 1 << 2,
WaterValveState = 1 << 3,
SteamValveState = 1 << 4,
MotorDriverState = 1 << 5
}
可以为命名的项目分配任何适合基础类型的值(在本例中为byte),因此如果您愿意,一个项目可以表示多个位。请注意,如果您想直接与 C 样式的位域进行互操作,您的第一个值应该从 最重要的位开始,而不是从最不重要的位开始。
要使用您的标志,只需声明一个新类型的变量或字段并执行您需要的任何按位运算:
BitFields bits = BitFields.None;
bits |= BitFields.VesselPresenceSw | BitFields.PumpState;
bits &= ~BitFields.VesselPresenceSw;
// etc.
从好的方面来说,使用[Flags] 声明的枚举在调试器中显示或转换为字符串时格式良好。例如,如果您要打印表达式BitFields.VesselPresenceSw | BitFields.PumpState,您将得到文本DrawerPresenceSw, PumpState。
有一个警告:enum 的存储将接受任何适合基础类型的值。这样写是完全合法的:
BitFields badBits = (BitFields)0xFF;
这将设置byte 大小的枚举的所有 8 位,但我们的命名值仅涵盖 6 位。根据您的要求,您可能希望声明一个仅包含“合法”标志的常量,您可以 & 反对。
如果您需要比这更丰富的内容,可以使用名为 BitArray 的框架级“位域”数据结构。但是,BitArray 是使用托管int[] 进行存储的引用类型。如果您想要一个可用于互操作目的或任何类型的内存映射的 struct,这对您没有帮助。