Wbudowane operacje wyliczania flag .NET są niestety dość ograniczone. Przez większość czasu użytkownicy nie są w stanie zrozumieć logiki operacji bitowej.
W .NET 4 HasFlag
dodano metodę, Enum
która pomaga uprościć kod użytkownika, ale niestety jest z nim wiele problemów.
HasFlag
nie jest bezpieczny dla typu, ponieważ przyjmuje dowolny typ argumentu wartości wyliczeniowej, nie tylko dany typ wyliczenia.
HasFlag
jest niejednoznaczny, czy sprawdza, czy wartość ma wszystkie czy jakiekolwiek flagi dostarczone przez argument wartości wyliczeniowej. Nawiasem mówiąc, to wszystko.
HasFlag
jest raczej powolny, ponieważ wymaga boksu, który powoduje przydziały, a tym samym więcej śmieci.
Po części ze względu na ograniczone wsparcie .NET dla wyliczeń flag, napisałem bibliotekę OSS Enums.NET, która rozwiązuje każdy z tych problemów i znacznie ułatwia radzenie sobie z wyliczeniami flag.
Poniżej znajdują się niektóre operacje, które udostępnia wraz z ich równoważnymi implementacjami przy użyciu samego środowiska .NET.
Połącz flagi
.NETTO flags | otherFlags
Enums.NET flags.CombineFlags(otherFlags)
Usuń flagi
.NETTO flags & ~otherFlags
Enums.NET flags.RemoveFlags(otherFlags)
Wspólne flagi
.NETTO flags & otherFlags
Enums.NET flags.CommonFlags(otherFlags)
Przełącz flagi
.NETTO flags ^ otherFlags
Enums.NET flags.ToggleFlags(otherFlags)
Ma wszystkie flagi
.NET (flags & otherFlags) == otherFlags
lubflags.HasFlag(otherFlags)
Enums.NET flags.HasAllFlags(otherFlags)
Ma dowolne flagi
.NETTO (flags & otherFlags) != 0
Enums.NET flags.HasAnyFlags(otherFlags)
Zdobądź flagi
.NETTO
Enumerable.Range(0, 64)
.Where(bit => ((flags.GetTypeCode() == TypeCode.UInt64 ? (long)(ulong)flags : Convert.ToInt64(flags)) & (1L << bit)) != 0)
.Select(bit => Enum.ToObject(flags.GetType(), 1L << bit))`
Enums.NET flags.GetFlags()
Usiłuję włączyć te ulepszenia do .NET Core i być może pełnej wersji .NET Framework. Możesz sprawdzić moją propozycję tutaj .