我想使用.NET Standard实现以下方法:
public static void SetFlag<TEnum>(ref TEnum value, TEnum flag)
where TEnum : Enum
我花了几个小时来尝试实现这一目标:
|
通过反射获取操作员似乎是不可能enum
的。dynamic
需要引用一个额外的包(Microsoft.CSharp.RuntimeBinder
),但我希望我的库保持纯净的.NET Standard一致性。我最近的想法是手动比较 TEnum
每个有效枚举类型的{byte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
}。但这感觉真的很奇怪又肮脏:
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)}");
那么,这真的是.NET(标准)在此提供的唯一选项吗?还是我所缺少的?期待您的提示!
编辑:不是这个问题的重复;我正在使用C#7.3和通用Enum
约束。
它不是最便宜的(所有东西都装箱了,有些反射,等等),但是您总是可以做这样的事情:
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);
}
}
您仍然有一些重复,但至少限于long/ulong
。如果可以假设您的flags枚举成员没有负值,则可以使用:
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);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句