【发布时间】:2009-09-10 08:31:29
【问题描述】:
更新:请参阅此问题的底部以了解 C# 解决方法。
你好,
考虑以下扩展方法:
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# 解决方法
Jon Skeet 已开始开发一个库,该库将带有约束的类编译为
IEnumConstraint,然后在构建后将其替换为System.Enum。我相信,这是目前最接近解决此问题的方法。见:
- 代码项目:http://code.google.com/p/unconstrained-melody/
- 博客条目:http://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for-enums-and-delegates.aspx
如果此解决方法不可行,您将不得不将库编写为 C++/CLI 代码,这不会限制可用于泛型类型约束的内容(请参阅下面我的答案中的代码。)
【问题讨论】:
-
也许除了非常罕见的情况外,在所有情况下都不需要这样的约束。谁知道...如果是这样的话,我会同意他们的:)
-
@Skurmedel:奇怪的是它被明确禁止......换句话说,规范变得更加复杂来限制它。我不明白为什么。也许 Eric Lippert 会解释 :)
-
是的,我同意 Jon Skeet 的观点,尽管它可能只是被忽略了(他们对约束使用了与类继承相同的继承检查)......但我真的不熟悉使用 C# 的内部工作原理。
-
Eric Lippert 之前发布过关于 C# 中的枚举类型约束的文章:stackoverflow.com/questions/1331739/enum-type-constraints-in-c/…
-
我明白了。我可以从他的回答中看出,即使有关闭编译器错误的选项,代码仍然无法工作?除非是这种情况,否则我不明白为什么要强制执行此限制(能够显式关闭 CS0702 错误会很好。)
标签: c# .net generics extension-methods