如何在.NET Standard中为泛型枚举类型设置枚举标志?

问题描述 投票:2回答:1

我想使用.NET Standard实现以下方法:

public static void SetFlag<TEnum>(ref TEnum value, TEnum flag)
    where TEnum : Enum

我花了几个小时试图实现这个目标:

  • 通过反射获得|算子似乎不像enums那样对于原始类型。
  • 使用dynamic需要引用一个额外的包(Microsoft.CSharp.RuntimeBinder),但我希望我的库保持纯.NET标准符合。

我的最新想法是手动比较TEnum与{bytesbyteshortushortintuintlongulong}的每个有效枚举类型。但这感觉非常奇怪和肮脏:

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(标准)在这里提供的唯一选择还是我缺少的选项?期待您的提示!

编辑:不是this question的副本;我正在使用C#7.3和通用的Enum约束。

c# .net reflection enums .net-standard
1个回答
3
投票

它不是最便宜的(一切都被盒装,有一些反射等),但你可以做这样的事情:

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。如果您可以假设您的标志枚举成员不会有负值,您可以使用:

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.