2013-04-25 13 views
6

Mam następujące flagi ENUM:C# wyliczenia - Sprawdź Flagi przed maską

[Flags] 
private enum MemoryProtection: uint 
{ 
    None    = 0x000, 
    NoAccess   = 0x001, 
    ReadOnly   = 0x002, 
    ReadWrite  = 0x004, 
    WriteCopy  = 0x008, 
    Execute   = 0x010, 
    ExecuteRead  = 0x020, 
    ExecuteReadWrite = 0x040, 
    ExecuteWriteCopy = 0x080, 
    Guard   = 0x100, 
    NoCache   = 0x200, 
    WriteCombine  = 0x400, 
    Readable   = (ReadOnly | ReadWrite | ExecuteRead | ExecuteReadWrite), 
    Writable   = (ReadWrite | WriteCopy | ExecuteReadWrite | ExecuteWriteCopy) 
} 

teraz mam instancji enum, że muszę sprawdzić, czy jest czytelny. Jeśli używam następujący kod:

myMemoryProtection.HasFlag(MemoryProtection.Readable) 

zawsze zwraca fałsz w moim przypadku, ponieważ myślę HasFlag sprawdzić czy posiada ono każdą flagę. Potrzebuję czegoś eleganckiego, aby tego uniknąć:

myMemoryProtection.HasFlag(MemoryProtection.ReadOnly)   || 
myMemoryProtection.HasFlag(MemoryProtection.ReadWrite)  || 
myMemoryProtection.HasFlag(MemoryProtection.ExecuteRead)  || 
myMemoryProtection.HasFlag(MemoryProtection.ExecuteReadWrite) 

Jak mogę to zrobić?

+0

Wymaga .NET 4.0 lub nowszy – linquize

Odpowiedz

7

Można włączyć stan dokoła, i sprawdzić, czy kompozyt enum ma flagę, zamiast sprawdzać flagę dla kompozytu, na przykład:

if (MemoryProtection.Readable.HasFlag(myMemoryProtection)) { 
    ... 
} 

Oto przykład:

MemoryProtection a = MemoryProtection.ExecuteRead; 
if (MemoryProtection.Readable.HasFlag(a)) { 
    Console.WriteLine("Readable"); 
} 
if (MemoryProtection.Writable.HasFlag(a)) { 
    Console.WriteLine("Writable"); 
} 

To drukuje Readable.

+0

Czytelnicy powinni pamiętać, że 'HasFlag' stały się dostępne z .NET 4.0. – Grinn

+0

W przypadku wyrażeń innych niż maska ​​maskująca to byłoby dobre podejście – GoldBishop

3

Spróbuj operatory bitowe:

[TestMethod] 
public void FlagsTest() 
{ 
    MemoryProtection mp = MemoryProtection.ReadOnly | MemoryProtection.ReadWrite | MemoryProtection.ExecuteRead | MemoryProtection.ExecuteReadWrite; 
    MemoryProtection value = MemoryProtection.Readable | MemoryProtection.Writable; 
    Assert.IsTrue((value & mp) == mp); 
} 
+0

Jest to preferowana metoda, jeśli zaimplementowano podejście z maską bitową. – GoldBishop

3

Tak, hasFlag sprawdza, czy każde pole bit (Flag) jest ustawiony.

Zamiast obcinać Readable jako kombinację wszystkich zabezpieczeń, które zawierają Read w nazwie, można obrócić kompozycję? Na przykład.

[Flags] 
private enum MemoryProtection: uint 
{ 
    NoAccess   = 0x000, 
    Read    = 0x001, 
    Write   = 0x002, 
    Execute   = 0x004, 
    Copy    = 0x008, 
    Guard   = 0x010, 
    NoCache   = 0x020, 
    ReadOnly   = Read, 
    ReadWrite  = (Read | Write), 
    WriteCopy  = (Write | Copy), 
    // etc. 
    NoAccess   = 0x800 
} 

Następnie można napisać kod jak:

myMemoryProtection.HasFlag(MemoryProtection.Read)