I want to implement the following method using .NET Standard:
public static void SetFlag<TEnum>(ref TEnum value, TEnum flag)
where TEnum : Enum
I spend hours in trying to achieve this:
| operator via reflection appears to be impossible for primitive types as enums are.dynamic requires referencing an extra package (Microsoft.CSharp.RuntimeBinder), but I would like my library to stay pure .NET Standard conform.My latest idea was to manually compare TEnum to each valid enum type of {byte, sbyte, short, ushort, int, uint, long, ulong}. But this feels really weird and dirty:
try
{
var v = (byte)(object)value | (byte)(object)flag;
value = (TEnum)(object)v;
return;
}
catch (InvalidCastException) { }
try
{
var v = (int)(object)value | (int)(object)flag;
value = (TEnum)(object)v;
return;
}
catch (InvalidCastException) { }
// ...
throw new NotSupportException($"Unknown enum type {typeof(TEnum)}");
So is this really the only option .NET (Standard) provides here or what I am missing? Looking forward to your hints!
Edit: Not a duplicate of this question; I am using C# 7.3 and the generic Enum constraint.
It's not the cheapest (everything gets boxed, there's some reflection, etc), but you could always do something like this:
private static void SetFlag<T>(ref T value, T flag) where T : Enum
{
// 'long' can hold all possible values, except those which 'ulong' can hold.
if (Enum.GetUnderlyingType(typeof(T)) == typeof(ulong))
{
ulong numericValue = Convert.ToUInt64(value);
numericValue |= Convert.ToUInt64(flag);
value = (T)Enum.ToObject(typeof(T), numericValue);
}
else
{
long numericValue = Convert.ToInt64(value);
numericValue |= Convert.ToInt64(flag);
value = (T)Enum.ToObject(typeof(T), numericValue);
}
}
You've still got some repetition, but at least it's restricted to long/ulong. If you can assume that your flags enum members won't have negative values, you can just use:
private static void SetFlag<T>(ref T value, T flag) where T : Enum
{
ulong numericValue = Convert.ToUInt64(value);
numericValue |= Convert.ToUInt64(flag);
value = (T)Enum.ToObject(typeof(T), numericValue);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With