如何在long类型中仅设置特定位?Setter实现方案咨询
基于long类型的位字段Setter实现方案
针对你遇到的仅修改指定特定位、不影响其他位的需求,核心思路是先清除目标位原有值,再写入新值,完全不需要依赖BitVector类,直接用位运算就能实现,且支持任意长度(只要不超过long的64位范围)。
核心步骤(通用模板)
对任意位字段,Setter都可以遵循这三个步骤:
- 过滤输入值:用字段对应的掩码截断输入值,防止超出字段长度的数据溢出到其他位
- 清除目标位:将data中对应字段的位全部置0,保留其他位不变
- 写入新值:将过滤后的输入值移位到目标位的位置,合并到data中
示例代码实现
结合你给出的代码,完整实现val1和val2的Setter:
public long data = 0x00; // Bit 0-1(2位) public byte val1 { get => (byte)(data & 3); // 等价于(data >>0 &3),简化写法 set { // 1. 过滤值:只保留低2位,避免超出范围 byte filteredValue = (byte)(value & 3); // 2. 清除原有Bit0-1的值 data &= ~3L; // 3L是long类型的掩码,防止整数溢出 // 3. 写入新值 data |= filteredValue; } } // Bit 2-9(对应你get方法中0x3FC的掩码逻辑) public byte val2 { get => (byte)((data >> 2) & 0x3FC); set { // 1. 过滤值:只保留符合0x3FC掩码的部分 byte filteredValue = (byte)(value & 0x3FC); // 2. 清除原有Bit2-9的值:掩码左移2位后取反,再与data做与运算 data &= ~((long)0x3FC << 2); // 3. 将过滤后的值移位到Bit2的位置,写入data data |= (long)filteredValue << 2; } }
关键细节说明
- 必须用long类型的掩码(比如
3L、(long)0x3FC),避免int类型掩码左移时出现溢出问题 - 过滤输入值是必要的:如果用户传入超过字段长度的值,能自动截断,防止破坏其他位的数据
- 该方案支持任意长度的字段(最大63位,因为long是64位有符号类型),完全覆盖你提到的24位字段需求
多线程场景补充
如果你的代码运行在多线程环境下,直接读写data会有线程安全问题,需要用原子操作替代:
// 以val1为例的原子Setter set { byte filteredValue = (byte)(value & 3); long originalData; long newData; do { originalData = data; // 计算新值:清除原有位 + 写入新值 newData = (originalData & ~3L) | filteredValue; } while (Interlocked.CompareExchange(ref data, newData, originalData) != originalData); }
内容的提问来源于stack exchange,提问作者user1957413
相关产品推荐
相关产品推荐

