枚举作为通用约束:微软不想实现它的原因是什么?

时间:2010-04-21 06:38:50

标签: c# enums

我意识到enum不能用作通用约束,Microsoft has declined to fix this bug

有什么理由?

3 个答案:

答案 0 :(得分:3)

您发布的链接说明原因:

  

并且是语言的某种任意限制

可能会发生变化:

  

如果我们重新打开约束作为一个功能,这将是我们将重新评估的事情之一。对于即将发布的版本,我们没有机会添加任何其他语言功能,因此您会将其视为“无法修复”,但它仍保留在我们的列表中以供将来考虑。

答案 1 :(得分:2)

我怀疑enum不被接受作为通用约束的原因是,虽然有一些事情可能会“期望”能够使用枚举约束的参数来做一个人无法做到的事情一个无约束的参数,唯一一个实际工作的参数就是调用非常慢的非泛型HasFlag;特别是,涉及在枚举及其相关基本类型之间进行转换的操作将不可用。允许一个不允许程序员以他们期望的方式使用变量的约束,但只增加了调用非常慢的非泛型方法的能力似乎并不值得。

实际上,我不认为无法使用Enum作为类型约束会造成损失,但是为了增加一个在做出决定时没有预料到的功能:扩展方法和他们与Intellisense的互动。如果写一个方法bool FlagCheck.HasAnyFlags<T>(T enum1, T enum2) where T:struct,它接受​​两个匹配类型的枚举,并检查一个是否包含任何另一个的标志[可以写出这样的方法比Enum.HasFlag快一个数量级。 ],在类型double的参数上调用它可能没有意义,但唯一的结果是这些事情将在运行时而不是编译时捕获。只有当一个人将这样的东西作为扩展方法时,缺少枚举约束才会变得烦人;在这种情况下,这意味着没有办法让Intellisense在HasAnyFlags类型的变量上提供enum,而不会弹出其他类型的变量。

顺便说一句,我认为我不同意enum约束的哲学,出于同样的原因,我不同意人们不能约束密封类型的规则。即使创建一个被限制为始终被密封的类型的泛型类型参数也没用,但是类型被密封在程序集的[也许是初步]版本中的事实意味着它总是如此。此外,如果一个类型是未密封但只有internal构造函数[通过工厂方法调用]我不知道用密封类替换它将是一个重大变化但是关于密封类型约束的规则

答案 2 :(得分:1)

底层类型问题和性能是有效的,但它们有解决方法,CLR和C ++ / CLI支持通用枚举约束。使用标记枚举一直不如我喜欢的可读性。 HasFlag有所帮助,但正如已经指出提高性能的空间。

我有this and several other useful enum extension/helper methods here。如果确实需要编写一个限制枚举类型的方法,那么该语言可以处理它,如果这些简单的方法,写入的内容并不是很难学习来自C#背景。

我怀疑我在C ++ / CLI中遇到的通用枚举类型的一些限制与它被视为&#34;不够重要的原因有关。&#34;例如,除了赋值之外,大多数有用的运算符都缺失。要使用TEnum 执行任何事情,您必须转换为基础类型,这可能会很昂贵,具体取决于它是如何完成的。考虑到添加/删除/测试标志的二进制操作非常快,添加单一类型转换要求会显着改变性能。在C ++ / CLI中转到(已知的)基础类型值可以快速非常以IL中实现的方式完成,等同于&#34;接受枚举参数并将其传递出去好像它实际上是基础类型&#34;。然而,在C ++ / CLI中执行这一操作是不可能的,并且需要Enum.ToObject调用,这是一种昂贵的转换。

我实施了一个基本上采用&#34; convertBackToTEnum&#34;方法并重写IL以完全按照ConvertToUnderlyingType方法的方式执行。

如果你搞砸并施放到错误的底层类型,演员也有风险。我很关注它,我写了一个T4脚本来为每个底层类型的每个操作生成单元测试(如果转换不正确,将导致问题的值)。

如果你需要编写支持它的方法,上面的项目有几个例子,包括类和方法约束。