Skip to content

Instantly share code, notes, and snippets.

@teoadal
Created June 25, 2025 19:36
Show Gist options
  • Save teoadal/a7395b5a96f8c6209bb61f5df706de1e to your computer and use it in GitHub Desktop.
Save teoadal/a7395b5a96f8c6209bb61f5df706de1e to your computer and use it in GitHub Desktop.
using System.Collections.Frozen;
using System.Runtime.CompilerServices;
namespace ConsoleApp1;
[SimpleJob(RuntimeMoniker.Net90)]
[SimpleJob(RuntimeMoniker.Net80)]
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
[MeanColumn, MemoryDiagnoser]
public class HasFlagBench
{
private Operator[] _flags = null!;
private Operator[] _values = null!;
[Benchmark(Baseline = true)]
public bool HasFlagMethod()
{
var result = false;
foreach (var flag in _flags)
{
foreach (var value in _values)
{
result = value.HasFlag(flag);
}
}
return result;
}
[Benchmark]
public bool BitwiseOperation()
{
var result = false;
foreach (var flag in _flags)
{
foreach (var value in _values)
{
result = (value & flag) != 0;
}
}
return result;
}
[Benchmark]
public bool SwitchCheck()
{
var result = false;
foreach (var flag in _flags)
{
foreach (var value in _values)
{
result = value.Is(flag);
}
}
return result;
}
[Benchmark]
public bool ArrayCheck()
{
var result = false;
foreach (var flag in _flags)
{
foreach (var value in _values)
{
result = value.Is_Array(flag);
}
}
return result;
}
[Benchmark]
public bool HashSetCheck()
{
var result = false;
foreach (var flag in _flags)
{
foreach (var value in _values)
{
result = value.Is_HashSet(flag);
}
}
return result;
}
[GlobalSetup]
public void Setup()
{
_flags =
[
Operator.NonOperator,
Operator.Comparison,
Operator.Logical,
Operator.Math,
Operator.Grouping
];
_values = Enum.GetValues<Operator>();
}
}
[Flags]
public enum Operator : short
{
None = 0x0,
// Flags
NonOperator = 0x0001,
Comparison = 0x0002,
Logical = 0x0004,
Math = 0x0008,
Grouping = 0x0010,
// Grouping Operators
OpenParen = 0x0100 | Grouping,
ClosedParen = 0x0200 | Grouping,
// Logical Operators
Not = 0x0300 | Logical,
Or = 0x0400 | Logical,
And = 0x0500 | Logical,
In = 0x0600 | Logical,
// Comparison Operators
Equals = 0x0700 | Comparison,
NotEquals = 0x0800 | Comparison,
LessThan = 0x0900 | Comparison,
LessThanOrEqual = 0x0A00 | Comparison,
GreaterThan = 0x0B00 | Comparison,
GreaterThanOrEqual = 0x0C00 | Comparison,
// Math Operators
Add = 0x0D00 | Math,
Subtract = 0x0E00 | Math,
Multiply = 0x0F00 | Math,
Divide = 0x1000 | Math,
Modulus = 0x1100 | Math,
// Specific non-operators
Whitespace = 0x2000 | NonOperator,
Quotes = 0x2100 | NonOperator,
Token = 0x2200 | NonOperator,
Bracket = 0x2300 | NonOperator,
}
public static class OperatorExtensions
{
private static readonly Operator[] NonOperatorValues =
[
Operator.Whitespace,
Operator.Quotes,
Operator.Token,
Operator.Bracket
];
private static readonly Operator[] ComparisonValues =
[
Operator.Equals,
Operator.NotEquals,
Operator.LessThan,
Operator.LessThanOrEqual,
Operator.GreaterThan,
Operator.GreaterThanOrEqual
];
private static readonly Operator[] LogicalValues =
[
Operator.Not,
Operator.Or,
Operator.And,
Operator.In
];
private static readonly Operator[] MathValues =
[
Operator.Add,
Operator.Subtract,
Operator.Multiply,
Operator.Divide,
Operator.Modulus
];
private static readonly FrozenSet<Operator> NonOperatorSet = NonOperatorValues.ToFrozenSet();
private static readonly FrozenSet<Operator> ComparisonSet = ComparisonValues.ToFrozenSet();
private static readonly FrozenSet<Operator> LogicalSet = LogicalValues.ToFrozenSet();
private static readonly FrozenSet<Operator> MathSet = MathValues.ToFrozenSet();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is(this Operator op, Operator flag) => flag switch
{
Operator.NonOperator => IsNonOperator(op),
Operator.Comparison => IsComparison(op),
Operator.Logical => IsLogical(op),
Operator.Math => IsMath(op),
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is_Array(this Operator op, Operator flag) => flag switch
{
Operator.NonOperator => IsNonOperator_Array(op),
Operator.Comparison => IsComparison_Array(op),
Operator.Logical => IsLogical_Array(op),
Operator.Math => IsMath_Array(op),
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is_HashSet(this Operator op, Operator flag) => flag switch
{
Operator.NonOperator => IsNonOperator_HashSet(op),
Operator.Comparison => IsComparison_HashSet(op),
Operator.Logical => IsLogical_HashSet(op),
Operator.Math => IsMath_HashSet(op),
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNonOperator(this Operator op) => op switch
{
Operator.Whitespace => true,
Operator.Quotes => true,
Operator.Token => true,
Operator.Bracket => true,
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsComparison(this Operator op) => op switch
{
Operator.Equals => true,
Operator.NotEquals => true,
Operator.LessThan => true,
Operator.LessThanOrEqual => true,
Operator.GreaterThan => true,
Operator.GreaterThanOrEqual => true,
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsLogical(this Operator op) => op switch
{
Operator.Not => true,
Operator.Or => true,
Operator.And => true,
Operator.In => true,
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsMath(this Operator op) => op switch
{
Operator.Add => true,
Operator.Subtract => true,
Operator.Multiply => true,
Operator.Divide => true,
Operator.Modulus => true,
_ => false
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNonOperator_Array(this Operator op) => Array.IndexOf(NonOperatorValues, op) > -1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsComparison_Array(this Operator op) => Array.IndexOf(ComparisonValues, op) > -1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsLogical_Array(this Operator op) => Array.IndexOf(LogicalValues, op) > -1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsMath_Array(this Operator op) => Array.IndexOf(MathValues, op) > -1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsMath_HashSet(Operator op) => MathSet.Contains(op);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsLogical_HashSet(Operator op) => LogicalSet.Contains(op);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsComparison_HashSet(Operator op) => ComparisonSet.Contains(op);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsNonOperator_HashSet(Operator op) => NonOperatorSet.Contains(op);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment