【问题标题】:Adding extension methods for all enums, not just a specific kind为所有枚举添加扩展方法,而不仅仅是特定类型
【发布时间】:2018-10-25 19:39:13
【问题描述】:

编辑:这篇文章不是重复的,其他解决方案不能让我使用按位运算符。

我想做这样的事情:

public static class EnumExt
{
    public static enum AddFlag(this enum e, enum flag) => e |= flag;
}

所以我可以这样使用它:

Color color = Red;
color.AddFlag(Color.Dark);

它只是更容易阅读。 我希望这个单一方法适用于所有枚举值,而不是为我计划使用的每个值进行覆盖。问题是,该代码不起作用,因为 enum 不是像int 这样的类型是。我尝试用泛型做一些事情:

public static class EnumExt
{
    public static T AddFlag<T>(this T e, T flag) 
        where T : Enum      // Can't constrain to Enum
    {
        return e = e | flag;
    }
}

还有这个:

public static T AddFlag<T>(this T e, T flag) 
    where T : struct
{
    if (!(typeof(T).IsEnum)) return default; 

    return e |= flag;      // Operator '|' cannot be applied to T
}

这有两个问题。因为它是struct,这意味着此方法将显示int 值。我使用struct 只是因为它是最接近Enum 的约束。如果它不是Enum,我将退出该方法,但这仍然不会让编译器知道eenum,即使它应该始终在这一点上。

还尝试使用where T : int 和使用强制转换,但int 是无效约束。

有没有办法做到这一点?

编辑:我已经尝试了两个建议作为解决问题的答案,但它们没有。带有IEnumConstraint 的那个不起作用,因为它说我的enum 没有从它继承,而且两个答案都不允许我实际执行return e |= flag;

// Doesn't work because C# won't allow bitwise operators on generic types 
// Because the constraint is still vague enough for non-enum values to slip through
public static T AddFlag<T>(this T e, T flag)
    where T : struct, IConvertible

// Doesn't work because enums don't inherit from IEnumConstraint
// Same as above
public static T AddFlag<T>(this T e, T flag)
    where T : struct, IEnumConstraint

我的猜测是,即使这些确实仅限于 Enum 值,其他一些类仍然有可能从 IEnumConstraintIConvertible 继承,因此按位运算符将不起作用,因为它仍然不是保证操作将可用于T

似乎唯一真正的解决方案是在 C# 7.3 中,它们允许您使用 System.Enum 作为约束。

【问题讨论】:

标签: c# generics enums constraints extension-methods


【解决方案1】:

AustinWBryan's solution 的一个可能改进是:

internal static class EnumExtensions
{
    public static bool IsDefinedAndNotDefault<T>(this T value)
        where T : Enum
    {
        return Enum.IsDefined(typeof(T), value) && !value.Equals(default(T));
    }
}

【讨论】:

    【解决方案2】:

    能够弄清楚。我必须从T 转换为object 然后转换为int,对int 值使用按位运算符,然后将其反转以获取结果。

    @mjwills 指出 C# 7.3 不会解决强制转换问题。它将修复的只是约束,我将能够删除抛出异常。

    public static T AddFlag<T>(this ref T e, T flag)
        where T : struct, IConvertible
    {
        if (!(typeof(T).IsEnum)) throw new ArgumentException("Value must be an enum");
    
        int added = (int)(object)e | (int)(object)flag;
    
        e = (T)(object)added;
    
        return e;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-17
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      相关资源
      最近更新 更多