Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Created December 6, 2024 14:23
Show Gist options
  • Save lucasteles/499045cb41d99e2b5aa213c1a1577849 to your computer and use it in GitHub Desktop.
Save lucasteles/499045cb41d99e2b5aa213c1a1577849 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
Check(Foo.A | Foo.B | Foo.C, Foo.B);
Check(Foo.A | Foo.B, Foo.C);
Check(Foo.A | Foo.C, Foo.None);
Check(Foo.A | Foo.B | Foo.C, Foo.B | Foo.C);
Check(Foo.A | Foo.B | Foo.D, Foo.B | Foo.C);
var setA = (Foo.B | Foo.C).Set(Foo.A).Set(Foo.C, false);
Console.WriteLine(setA);
Check(setA, Foo.A);
var multiFlags = Foo.A | Foo.B | Foo.C | Foo.E;
Console.WriteLine("\nList unique values :");
foreach(var enumValue in multiFlags.GetUniqueFlags())
Console.WriteLine($"- {enumValue}");
Console.WriteLine("\nList all values :");
foreach(var enumValue in multiFlags.GetFlags())
Console.WriteLine($"- {enumValue}");
Console.WriteLine("🌄");
static void Check(Foo e, Foo flag) {
Console.WriteLine($"HasFlag ({flag}) in ({e}) = {e.HasFlag(flag)}");
Console.WriteLine($"HasAllFlag ({flag}) in ({e}) = {e.HasAll(flag)}");
Console.WriteLine($"HasAnyFlag ({flag}) in ({e}) = {e.HasAny(flag)}");
Console.WriteLine();
}
[Flags]
public enum Foo {
None = 0,
A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
D = 1 << 3,
E = 1 << 4,
AB = A | B,
}
static class EnumExt
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasAll<T>(this T value, in T flags) where T : struct, Enum, IConvertible
{
var bits = value.ToUInt64(null);
var flagBits = flags.ToUInt64(null);
return flagBits != 0 && (bits & flagBits) == flagBits;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasAny<T>(this T value, in T flags) where T : struct, Enum, IConvertible
{
var bits = value.ToUInt64(null);
var flagBits = flags.ToUInt64(null);
return (bits & flagBits) is not 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Set<T>(this T value, in T flags, bool enabled = true) where T : struct, Enum, IConvertible
{
var bits = value.ToUInt64(null);
var flagBits = flags.ToUInt64(null);
var result = enabled ? bits | flagBits : bits & ~flagBits;
return Unsafe.As<ulong, T>(ref result);
}
public static IEnumerable<T> GetUniqueFlags<T>(this T flags) where T : struct, Enum, IConvertible
{
var flag = 1UL;
var flagBits = flags.ToUInt64(null);
foreach (var value in Enum.GetValues<T>())
{
var bits = value.ToUInt64(null);
while (flag < bits)
flag <<= 1;
if (flag == bits && (bits & flagBits) == bits)
yield return value;
}
}
public static IEnumerable<T> GetFlags<T>(this T flags) where T : struct, Enum, IConvertible
{
var flagBits = flags.ToUInt64(null);
foreach (var value in Enum.GetValues<T>())
{
var bits = value.ToUInt64(null);
if ((bits & flagBits) == bits)
yield return value;
}
}
}
HasFlag (B) in (AB, C) = True
HasAllFlag (B) in (AB, C) = True
HasAnyFlag (B) in (AB, C) = True
HasFlag (C) in (AB) = False
HasAllFlag (C) in (AB) = False
HasAnyFlag (C) in (AB) = False
HasFlag (None) in (A, C) = True
HasAllFlag (None) in (A, C) = False
HasAnyFlag (None) in (A, C) = False
HasFlag (B, C) in (AB, C) = True
HasAllFlag (B, C) in (AB, C) = True
HasAnyFlag (B, C) in (AB, C) = True
HasFlag (B, C) in (AB, D) = False
HasAllFlag (B, C) in (AB, D) = False
HasAnyFlag (B, C) in (AB, D) = True
AB
HasFlag (A) in (AB) = True
HasAllFlag (A) in (AB) = True
HasAnyFlag (A) in (AB) = True
List unique values :
- A
- B
- C
- E
List all values :
- None
- A
- B
- AB
- C
- E
🌄
{
"version": 1,
"target": "Run",
"mode": "Debug"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment