在C#3.0中是否存在针对"特殊类"Enum的泛型类型约束的解决方法?

Bli*_*ixt 10 .net c# generics extension-methods

更新:请参阅此问题的底部以获取C#解决方法.

嗨,您好,

请考虑以下扩展方法:

public static bool HasFlags<T>(this T value, T flags)
    where T : System.Enum
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

您可能知道,这将在编译时抛出一个错误,因为通常不允许继承类System.Enum.问题是使用enum关键字指定的任何枚举实际上都继承自System.Enum,因此上述代码将是仅将扩展方法限制为枚举的理想方法.

现在显而易见的解决方法是使用Enum而不是T,但是你失去了泛型类型的好处:

MyEnum e;
e.HasFlags(MyOtherEnum.DoFunkyStuff);
Run Code Online (Sandbox Code Playgroud)

上面的代码会使用泛型类型抛出编译时错误,而它只能使用Enum类型抛出运行时错误(如果我实现它的话).

是否有任何编译器选项可用于关闭约束检查,还是有其他一些漂亮的方法来做到这一点?

在建议之前,我想说我不会使用where T : struct或者其他一些,从那以后你就可以做一些奇怪的事情了123.HasFlags(456).

我很难理解为什么会出现这个错误...这是你要使用的同样的问题where T : System.Object,但是你有where T : class...为什么没有where T : enum

C#解决方法

Jon Skeet已经开始研究一个库,该库将带有约束的类编译为a IEnumConstraint,然后将其替换为System.Enumpost-build.我相信,这是目前最接近解决这个问题的人.

看到:

如果此解决方法不可行,则必须将库编写为C++/CLI代码,这不会限制可用于泛型类型约束的内容(请参阅下面的答案中的代码.)

Jon*_*eet 10

编辑:现在可以通过ildasm/ilasm:UnconstrainedMelody支持此库.


C#团队的成员此前曾表示,他们会喜欢能够支持where T : Enumwhere T : Delegate,但它从来没有足够高的优先级.(我不确定在第一时间有限制的原因是什么,当然......)

C#中最实用的解决方法是:

public static bool HasFlags<T>(this T value, T flags) where T : struct
{
    if (!(value is Enum))
    {
        throw new ArgumentException();
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这会丢失编译时检查"enum-ness",但会检查你在两个地方都使用相同的类型.当然,它也有检查的执行时间惩罚.在第一次调用之后,通过使用通用嵌套类型来实现在静态构造函数中抛出异常,可以避免执行时间损失:

public static bool HasFlags<T>(this T value, T flags) where T : struct
{
    if (!(value is Enum))
    {
        throw new ArgumentException();
    }
    return EnumHelper<T>.HasFlags(value, flags);
}

private class EnumHelper<T> where T : struct
{
    static EnumHelper()
    {
        if (!typeof(Enum).IsAssignableFrom(typeof(T))
        {
            throw new InvalidOperationException(); // Or something similar
        }
    }

    internal static HasFlags(T value, T flags)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

正如Greco所提到的,您可以在C++/CLI中编写该方法,然后从C#引用类库作为另一种选择.

  • @Yngvar:嗯,现在是 codeblog.jonskeet.uk,所以:http://codeblog.jonskeet.uk/2009/09/10/generic-constraints-for-enums-and-delegates/ (2认同)