2013-07-17 31 views
1

對不起,如果這是一個重複的問題,我試圖搜索,但我找不到任何與我的問題有關的東西。C#字節查找字符串表示的所有位設置/未設置

我有一個字節值,其中每個位(或一組位)意味着什麼。我有一個自定義屬性的枚舉定義這些位,像這樣:

[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

是否有一種更有效的方法來獲取字節中每個位集的字符串表示形式,考慮到可能有一些比特組意味着完全不同於設置了各個比特組的比特組?

感謝 仙人

+0

當然,它的'(LowBeep | MediumBeep)= HighBeep'?否則'HighBeep'將爲零。 – harold

回答

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運算符,但它是一樣的。

+0

我想過這樣做,但是如果有多個位組成一個設置,那麼這個掩碼會是什麼?在我的例子中,'HighBeep'字節掩碼是什麼? – Rishi

+0

此外,在這段代碼中,我似乎無法弄清楚你在哪裏使用枚舉。它本質上是發送一個字節並將其與本地掩碼變量進行比較,對嗎?如果我嘗試使用枚舉值執行「if」語句,我會得到一個編譯器錯誤,基本上告訴我我不能和一個字節和一個枚舉值。 – Rishi

+0

對不起。你可以將你的bitflag枚舉轉換爲一個int。請參閱下面的更新源。 – Bjoern

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) 
    { 
// ... 
    } 
} 
+0

當然。這意味着雖然我必須爲每種可能的組合設置一個掩碼,對嗎? 沒有特別的理由使用移位運算符。它使我更容易閱讀,查看轉換是多少,並且知道將哪個位映射到該枚舉值。無需弄清楚它是否是第8位的第7位。 – Rishi

+0

如果它適合你,你可以從最低位開始。你需要什麼樣的口罩取決於你的具體情況。如果這是一種常見的情況,爲什麼不呢?在我以前的工作中,我需要一個掩碼來查明我們的硬件設備的狀態(找到的卡,開機等)並且工作正常 – Bjoern