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.我相信,这是目前最接近解决这个问题的人.看到:
- 代码项目: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代码,这不会限制可用于泛型类型约束的内容(请参阅下面的答案中的代码.)
Jon*_*eet 10
编辑:现在可以通过ildasm/ilasm:UnconstrainedMelody支持此库.
C#团队的成员此前曾表示,他们会喜欢能够支持where T : Enum和where 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#引用类库作为另一种选择.
| 归档时间: |
|
| 查看次数: |
3438 次 |
| 最近记录: |