1

我正在从医疗设备中提取字节流,并且遇到了一个非常烦人的数据结构。基本上,我得到了一个 2 字节的块,其中每个位代表一个布尔值。这种结构在字节流中出现得足够频繁,可以围绕它开发一个结构/类,但在每种情况下,这些位意味着完全不同的东西。

所以首先我设置了一堆枚举来表示位结构可能具有的所有不同定义。(请注意,并非每个定义都使用每个位。有时重要位之间会出现中断。)

编辑:删除了所有看起来像“标志”的名称。我没有使用 [Flags] 属性,这似乎是一个争论点/混淆点。枚举值只是映射到我的 BitArray 中的索引。

public enum RecordInfo { AM_TEST = 0, PM_TEST, TEST_VALIDITY };
public enum RecordAlerts { ALERT1 = 0, ALERT2, ALERT3, ALERT4, VALIDATED = 15 };

然后创建这个容器来保存实际的位:

public struct TwoBytes<TEnum> where TEnum : struct, IConvertible
{
    private BitArray _bits = new BitArray(2);
}

这似乎可以按我的需要工作,直到我想根据枚举名称索引我的结构。假设我有一个名为 Alerts 的 TwoByte 结构,它包含一些位值。如果我想获得这样的特定标志:

bool alert3Set = Alerts[RecordAlerts.ALERT3]

我最终得到了一个真正令人发指的索引函数。这就是我现在所拥有的:

public bool this[TEnum name]
{
    get
    {
        int index = Enum.GetValues(typeof(TEnum)).Cast<TEnum>().ToList().Where(x => x.Equals(name)).Cast<int>().First();
        return _bits[index];
    }
}

现在它起作用了,够疯狂的。但是 LINQ 链看起来确实很糟糕,并且需要一段时间才能破译它实际上在做什么。

是否有一种更简洁、更有效的方式将通用枚举“名称”转换为其整数值?或者我是否更适合使用字典(或其他对象)来表示位结构定义?

4

3 回答 3

3

只要TEnum您使用的每一个都来自int(默认),而不是来自其他数字类型,这将起作用:

public bool this[TEnum name]
{
    get
    {
        int index = (int)(object)name;
        return _bits[index];
    }
}

如果您想支持enum从较小类型派生的 s (以及仅使用 支持范围内的值的枚举int),我会使用:

public bool this[TEnum name]
{
    get
    {
        int index = Convert.ToInt32(name);
        return _bits[index];
    }
}

(完全支持从无法隐式转换为intuintlong和的类型派生的枚举ulong变得更加复杂,因为BitArray的索引器使用int

于 2013-08-16T16:24:14.713 回答
1

我认为一点 OOP 会让你的生活更轻松。您可以引入代表您收到的数据的类,并具有有意义的属性名称。每个类都可以将您的 BitArray 接受到构造函数中并将其解析为属性。

在您的程序中,您可以使用这些类而不是摆弄位。

于 2013-08-16T16:24:41.060 回答
1

正如 FrankPI 在评论中所建议的那样,为什么不使用一个enum其值真正代表每一位的值,而不是使用一个中间值BitArray呢?

[Flags]
public enum RecordFlags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8, FLAG5 = 0x10, VALIDATED = 0x8000 };

var readFlags = (RecordFlags) ((bytes[0] << 8) | bytes[1]);
bool hasFlag2 = (readFlags & RecordFlags.Flag2) != 0;
于 2013-08-16T16:33:35.733 回答