C#字节查找所有位设置/未设置的字符串表示

时间:2013-07-17 15:34:49

标签: c# enums bit-manipulation custom-attributes

很抱歉,如果这是一个重复的问题,我尝试搜索,但我找不到任何与我的问题有关的内容。

我有一个字节值,其中每个位(或位组)意味着什么。我有一个带有自定义属性的枚举来定义这些位,如下所示:

[Flags]
public enum Config4
{
    [StringValue("Enable good-read beep")]
    GoodReadBeep = 1 << 0,
    [StringValue("Low beeper volume")]
    LowBeep = 1 << 1,
    [StringValue("Medium beeper volume")]
    MediumBeep = 1 << 2,
    [StringValue("Low beeper frequency")]
    LowFrequency = 1 << 3,
    [StringValue("Medium beeper frequency")]
    MediumFrequency = 1 << 4,
    [StringValue("Medium beeper duration")]
    MediumDuration = 1 << 5,
    [StringValue("Long beeper duration")]
    LongDuration = 1 << 6,
    [StringValue("Reserved")]
    Reserved = 1 << 7
}

问题在于,除了这些单独的定义之外,比特的对(或甚至组)被定义为其他东西。例如,(LowBeep | MediumBeep) = HighBeep

假设我有一个字节值47,我想找到字符串表示。我实现的方法当前涉及查找字节中设置的位数,然后迭代这些位并从枚举中追加字符串值。如下所示:

for (int i = 0; i < bitsSet.Count; i++)
{
    answer += ((ConfigDataHolder.Config4)bitsSet[i]).GetStringValue() + ", ";
}

这在定义位组时会出现问题。在上述情况中,47将包含MediumBeepLowBeep,因此字符串表示应分别为HighBeep而不是MediumBeepLowBeep

是否有一种更有效的方法来获取字节中每个位集的字符串表示,因为可能存在一些位组,这意味着与单个位设置完全不同的位?

由于 仙人

2 个答案:

答案 0 :(得分:1)

您可以使用位掩码。看看这里的小例子:

[Flags]
public enum MySettings
{
    SettingA=1,
    SettingB=2,
    SettingC=4,
    SettingD=8
}

class Program
{
    static void Main(string[] args)
    {
        byte mySettings1 = 7;
        byte mySettings2 = 2;

        Console.WriteLine("Analyse mySetting1");
        AnalyseSettings(mySettings1);
        Console.WriteLine("Analyse mySetting2");
        AnalyseSettings(mySettings2);

        Console.ReadKey();
    }

    private static void AnalyseSettings(byte mySettings)
    {
        byte maskA = 1;
        byte maskB = 2;
        byte maskC = 4;
        byte maskD = 8;

        // Compare with bitwise and 

        if ((mySettings & maskA) == maskA)
        {
            Console.WriteLine("A Selected");
        }

        if ((mySettings & maskB) == maskB)
        {
            Console.WriteLine("B Selected");
        }
        if ((mySettings & maskC) == maskC)
        {
            Console.WriteLine("C Selected");
        }
        if ((mySettings & maskD) == maskD)
        {
            Console.WriteLine("D Selected");
        }
    }
}

按比例进行比较非常快,您可以将结果添加到字符串构建器中。 我不在我的枚举声明中使用shift运算符,但它是一样的。

答案 1 :(得分:0)

您也可以将它们组合在一起。见这里:

        byte maskAndB = 3;
        if ((mySettings & maskAndB) == maskAndB)
        {
            Console.WriteLine(" A and B selected");
        }

这就像数字的二进制表示。 11 = 3且101 = 5。

我想知道您为什么要使用移位运算符?您还使用左移,从数据类型的最高位开始。

您还可以将枚举转换为int并再次进行检查:

[Flags]
public enum MySettings
{
    SettingA=1,
    SettingB=2,
    SettingC=4,
    SettingD=8
}

class Program
{
    static void Main(string[] args)
    {
        var settingsFlags1 = MySettings.SettingA | MySettings.SettingB;
        var settingsFlags2 = MySettings.SettingB | MySettings.SettingC | MySettings.SettingD;


        int mySettings1 = (int)settingsFlags1;
        int mySettings2 = (int)settingsFlags2;

        Console.WriteLine("Analyse mySetting1");
        AnalyseSettings(mySettings1);
        Console.WriteLine("Analyse mySetting2");
        AnalyseSettings(mySettings2);

        Console.ReadKey();
    }

    private static void AnalyseSettings(int mySettings)
    {
// ...
    }
}