c# - C# 3.0 中 "special class"枚举的泛型类型约束是否有解决方法?

标签 c# .net generics extension-methods

<分区>

Update: See the bottom of this question for a C# workaround.

你好,

考虑以下扩展方法:

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

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

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

MyEnum e;
e.HasFlags(MyOtherEnum.DoFunkyStuff);

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

是否有任何编译器选项可用于关闭约束检查,或者是否有其他一些巧妙的方法来执行此操作?

在建议之前,我想说我不会使用 where T : struct 或类似的东西,从那时起你就可以做一些奇怪的事情,比如 123 .HasFlags(456).

我很困惑为什么会出现这个错误...这与您使用 where T : System.Object 时遇到的问题相同,但为此您有 where T : class... 为什么没有 where T : enum

C# workaround

Jon Skeet has started work on a library that compiles classes with a constraint to an IEnumConstraint, which is then replaced with System.Enum post-build. This is, I believe, the closest one can get to working around this issue at this time.

See:

If this workaround is unfeasible, you will have to write your library as C++/CLI code, which does not limit what can be used for generic type constraints (see the code in my answer below.)

最佳答案

编辑:现在有一个库可以通过 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();
    }
    // ...
}

这会丢失编译时对“枚举性”的检查,但会检查您是否在两个地方使用相同的类型。当然,它也有检查的执行时间惩罚。您可以通过对在静态构造函数中抛出异常的实现使用通用嵌套类型来避免第一次调用后的执行时间惩罚:

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)
    {
        ...
    }
}

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

关于c# - C# 3.0 中 "special class"枚举的泛型类型约束是否有解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1404077/

相关文章:

c# - Log4Net/C# - 禁用默认日志记录

c# - RavenDB Collection "in"集合查询

c# - 在 Windows Phone 上设计媒体播放器的好方法是什么?

c# - 使用什么样的数据结构?

c# - 为位图寻找最佳调色板

swift - 直接对泛型类型进行类型约束与使用 'where' 子句之间是否存在实际差异?

java - 为什么反射返回两种方法,而只有一种实现?

c# - 为什么 Visual Studio 向我的命名空间添加一个 at 符号 (@)?

c# - 编码的 UI 测试记录新测试覆盖 UIMap.Designer.cs 更改

kotlin - 如何防止 Kotlin 中的类型删除?