Extension Methods die Zweite – Bitmasken auf gesetzte Werte prüfen

Vor Kurzem hatte ich bereits über den Sinn von Extension Methods geschrieben und bin jetzt auf ein weiteres sehr gutes Beispiel für deren Verwendung gestoßen:  Die Erweiterung einer Enumeration um Bitmasken auf gesetzte Werte zu prüfen.

Dank des Attributes „Flags“ wird aus einer einfachen Enumeration eine Bitmaske, siehe Beispiel:

[Flags]
public enum AccessRights
{
   None=0,
   Read,
   Write,
   Execute
}

Die Erweiterungsmethoden prüfen per Bitvergleich ob alle übergebenen Flags im aktuellen Objekt gesetzt sind. Dies geht über eine einfache UND Verknüpfung welche alle Bits nullt die nicht in beiden Werten gesetzt sind. Entspricht das Endergebnis den hineingegebenen Flags, sind sie alle gesetzt. Ist es jedoch 0 hat keines überlebt sprich die angegeben Flags waren nicht gesetzt.

public static class AccessRightsExtensions
{
   public static bool IsSet(this AccessRights value, AccessRights flags)
   {
      return (value & flags) == flags;
   }

   public static bool IsNotSet(this AccessRights value, AccessRights flags)
   {
      return (value & flags) == 0;
   }
}

Oder um es noch einmal in Bitschreibweise zu machen

   IsSet:
   value = 011101
   flags = 011000
         & 011000 == flags -> true

   IsNotSet:
   value = 011101
   flags = 100010
         & 000000 == 0 -> true
 

Zum Abschluss gibt es jetzt noch ein kleines Beispiel wie diese Methoden eingesetzt werden könnten:

public class UserFile
{
   private AccessRights Rights;

   public bool IsVisibleToUser
   {
     get
     {
        return Rights.IsSet(AccessRights.Read);
     }
   }

   public Stream OpenReadWrite()
   {
       if(Rights.IsNotSet(AccessRights.Read | AccessRights.Write))
       {
           throw new Exception("Insufficient privileges");
       }

       ...
   }

Verwirrend mag auf den ersten Blick die Oder-Verkettung innerhalb von OpenReadWrite sein. Denn im Grunde möchte man ja prüfen ob beide Rechte gesetzt sind. Da es sich aber um eine bitweise Verkettung handelt entspricht das Oder an dieser Stelle einem Und.