索引BitArray,其中位由通用枚举定义

时间:2013-08-16 16:19:58

标签: c# generics enums

我正在从医疗设备中拉出一串字节,并且遇到了一个非常讨厌的数据结构。基本上,我得到一个2字节的块,其中每个位代表一个布尔值。这个结构在字节流中经常显得足以在它周围开发一个struct /类,但在每个实例中,这些位意味着完全不同的东西。

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

编辑:删除了所有看起来像“旗帜”的名字。我没有使用[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链看起来非常残酷,需要一段时间来破译它实际上在做什么。

是否有更简洁,更有效的方法将通用枚举'name'转换为整数值?或者我是否更适合使用Dictionary(或其他一些对象)来表示位结构定义?

3 个答案:

答案 0 :(得分:3)

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

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

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

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

(完全支持从无法隐式转换为int的类型派生的枚举,如uintlongulong,会变得更复杂,因为{ {1}}的索引器使用BitArray

答案 1 :(得分:1)

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

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

答案 2 :(得分: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;