微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#3.0中的“特殊类”枚举是否存在通用类型约束的解决方法?

参见英文答案 > Anyone know a good workaround for the lack of an enum generic constraint?10个

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.问题是使用枚举关键字指定的任何枚举实际上都是继承自System.Enum,因此上述代码将是将扩展方法限制为枚举的理想方式.

在这里明显的工作是使用枚举而不是T,但是你失去了通用类型的好处:

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

上面的代码将使用泛型类型抛出编译时错误,而它只能使用枚举类型(如果我实现它)来引发运行时错误.)

有没有任何编译器选项可以用来关闭约束检查,还是有其他一些漂亮的方法呢?

在建议之前,我想说,我不会使用T:struct或其他一些,因为你可以做一些奇怪的东西,如123.HasFlags(456).

我很遗憾为什么这个错误存在于所有…这是同样的问题,你会得到使用在哪里T:System.Object,但是,你有哪里T:类…为什么没有在哪里T:枚举?

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:

  • Code project: 07001
  • Blog entry: 07002

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#团队的成员之前曾表示过希望能够支持T:Enum和T:T代表的地位,但这并不是一个很高的优先级. (我不知道有什么理由是有限制在第一位,诚然…)

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/C++LI中编写该方法,然后从C#引用类库作为另一个选项.

原文地址:https://www.jb51.cc/csharp/95459.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐