自定义通用 SetFlag / UnsetFlag 扩展方法

Custom generic SetFlag / UnsetFlag extension methods

出于幼稚的天真,我决定为枚举构建通用的 SetFlagUnsetFlag 扩展方法,这样就没有人需要反复阅读我的代码中的按位运算符:

public static void SetFlag<T>(this T en, T flag)  where T : Enum {
    en |= flag;
}

public static void UnsetFlag<T>(this T en, T flag) where T : Enum
{
    en &= ~flag;
}

现在我得到的错误是 operator |= is not applicable to types T and T and operator ~ is not applicable to type T .

我认为我必须将 T 更改为类型“Enum with HasFlags”。这是问题的真正根源吗?我该如何改变它?

这是我的方法。正如我在对该问题的评论中所说,我强烈反对在生产代码中使用此方法:

    public static T SetFlag<T>(this T en, T flag) where T : struct, IConvertible
    {
        int value = en.ToInt32(CultureInfo.InvariantCulture);
        int newFlag = flag.ToInt32(CultureInfo.InvariantCulture);

        return (T)(object)(value | newFlag);
    }

    public static T UnsetFlag<T>(this T en, T flag) where T : struct, IConvertible
    {
        int value = en.ToInt32(CultureInfo.InvariantCulture);
        int newFlag = flag.ToInt32(CultureInfo.InvariantCulture);

        return (T)(object)(value & ~newFlag);
    }

用法:

[Flags]
public enum Flags
{
    None = 0, A = 1, B = 2, C = 4
}

Flags flags = Flags.A.SetFlag(Flags.C);
flags = flags.UnsetFlag(Flags.C);

如你所见,我使用了它,每个枚举都实现了 IConvertible。所以我在这个接口上定义了扩展方法,它还提供了一种将枚举值转换为 int 的便捷方法。这样做的副作用是您可以将此方法用于实现此接口的所有其他类型。所以你可以滥用这个方法来做这样的事情:

int a = 0;
a = a.SetFlag(5); // a == 5
a = a.UnsetFlag(4); // a == 1