C#中的枚举类型约束

Tay*_*ese 149 .net c# enums

可能重复:
任何人都知道缺少枚举通用约束的好方法?

C#不允许对Enums 进行类型约束的原因是什么?我确信疯狂背后有一种方法,但我想明白为什么不可能.

以下是我希望能够做到的(理论上).

public static T GetEnum<T>(this string description) where T : Enum
{
...
}
Run Code Online (Sandbox Code Playgroud)

SLa*_*aks 146

实际上,这可能是一个丑陋的伎俩.但是,它不能用于扩展方法.

public abstract class Enums<Temp> where Temp : class {
    public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
        return (TEnum)Enum.Parse(typeof(TEnum), name); 
    }
}
public abstract class Enums : Enums<Enum> { }

Enums.Parse<DateTimeKind>("Local")
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以Enums<Temp>使用Tempas 提供私有构造函数和公共嵌套抽象继承类Enum,以防止非枚举的继承版本.

请注意,您不能使用此技巧来制作扩展方法.

  • 这非常棒,并且不,@bsnote,运行时检查永远不会比编译时检查更好,因为可以进行编译时检查. (22认同)
  • @bsnote:这并不妨碍你在编译时传递`int`或`DateTime`. (4认同)
  • 更优雅的方式:http://stackoverflow.com/questions/1331739/enum-type-constraints-in-c/5995541#5995541 (2认同)
  • @hypehuman:为了防止你使用`Enums <SomeOtherType>`(除了`object`和`ValueType`).这些是满足`:class`并且具有符合`:struct`的子类型的唯一类型. (2认同)

Eri*_*ert 92

这是偶尔要求的功能.

正如我喜欢指出的那样,所有功能都没有实现,直到有人设计,规格,工具,测试,文档和发布功能.到目前为止,没有人为此做过.没有特别不寻常的原因; 我们还有许多其他的事情要做,预算有限,而且这个从来没有超越过"这不是很好吗?" 语言设计团队的讨论.

CLR不支持它,所以为了使它工作,除了语言工作之外,我们还需要做运行时工作. (见答复评论)

我可以看到有一些不错的使用案例,但没有一个是如此引人注目,以至于我们做这项工作,而不是更频繁要求的数百个其他功能之一,或者更具吸引力和更远的功能用例.(如果我们要使用这段代码,我会亲自优先考虑委托约束方式,就像枚举约束一样.)

  • 那么,问问自己什么更有可能?该规范是错误的,而且Jon的实现是虚构的,或者我错误地记录或误解了一年前我与CLR家伙的谈话? (44认同)
  • 不知怎的,我之前错过了这篇文章.在另一个问题中,这篇博文已被链接:[缺失通用案例(解析方法)](http://weblogs.asp.net/kennykerr/The-Case-of-the-Missing-Generic-_2800_Parse- Method_2900_)这表明它*在IL中可用*.我似乎记得以前尝试过它并且它正在工作,尽管那可能是`Delegate`.如果它可能意味着从C#5中删除了限制,我会很乐意再尝试一下(哎呀,多*多*).(我假设C#4现在被锁定了.) (40认同)
  • CLR确实支持它,至少根据我对规范第166页的理解. (18认同)
  • 我很困惑为什么你说CLR不支持Enum约束,因为它根据CLI ECMA文件的第166/167页(http://www.ecma-international.org/publications/files/ECMA)进行了说明. -ST/Ecma-335.pdf)(即,除非CLR不符合CLI规范)和Jon Skeet在Unconstrained Melody中的工作(http://code.google.com/p/unconstrained-melody/ ). (14认同)
  • 该功能未实现 - 它是不允许的.下面的SLaks解决方案不是_implementing_功能的一种方式 - 它是_removing_ CS0702错误的一种方式.由于将通用参数约束为从Enum继承是合理且明显有效的,因此添加规则以明确禁止它似乎很奇怪. (12认同)
  • FWIW,[C#7.3增加了枚举约束](https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-preview-relnotes#csharp) (11认同)
  • 我不明白这是怎么回事.相反,基态将允许它,并且在有人使CS0702编译器错误之前不存在限制. (5认同)
  • @Tom:好吧,让我们考虑一下.假设我们有`void M <T>(T t)其中T:System.Enum {}`问题一:这是合法的吗?`M((System.Enum)null);`看起来它应该是合法的,看起来类似推断看起来应该推断`T`是`System.Enum`,看起来肯定看起来像是约束了.因为`System.Enum`是一个引用类型,所以它是null是完全合法的.**你想要这个程序是合法的吗?**现在我们有一个我们可以争论的设计问题,现在你知道我花了大约七年的生命. (3认同)
  • 有趣的是你提到了委托约束,因为我也很乐意看到那些. (2认同)
  • 上次我听到与CLR家伙的谈话时,他们说他们没有适合它的装备,但我完全有可能误解他们在说什么. (2认同)
  • 让我们这样说吧 - 有没有办法用ILASM做到这一点? (2认同)
  • 嘿@EricLippert,因为这仍然没有在几年后回答,你能不能评论这个具体点:这真的是一个需要设计,规格,实施,测试等功能吗?功能是否已经存在(对泛型类型的限制)?为什么约束`where T:Enum`需要特殊处理(即需要设计的任何东西,专门用于此约束的任何东西,这些约束不包含在泛型类型约束功能中)? (2认同)
  • 谢谢你的回答,@ EricLippert!让我澄清一下我的意思,如果你能回答我会很高兴:我们所讨论的特征_已经是语言的一部分_给定一个非密封的类`C`可以使用类型约束` T:C`.语法很清楚,编译器和运行时都支持它.但是有意识地决定禁止"T:System.Enum".所以我的问题是`System.Enum`有什么特别之处?为什么它不能像任何其他类一样被对待?是什么让像任何其他类一样对待System.Enum`构成了"新功能"? (2认同)

And*_*doi 16

public static T GetEnum<T>(this string description) where T : struct
{
    return (T)Enum.Parse(typeof(T), description);
}
Run Code Online (Sandbox Code Playgroud)

它能回答你的问题吗?

  • 不!问题是将类型参数T缩小到Enum.'struct'太宽泛,包括int,float,double,DateTime和其他类型,甚至可以由用户定义为结构. (18认同)
  • 是的!正是我需要编写我的通用方法.进一步限制直接枚举将是很好的,但在我认为的大多数情况下并非绝对必要. (3认同)
  • 如果您愿意,可以进行运行时检查.我做了:!typeof(T).IsEnum (2认同)

Sim*_*mon 7

IL编织使用ExtraConstraints

你的守则

public static T GetEnum<[EnumConstraint] T>(this string description)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

什么被编译

public static T GetEnum<T>(this string description) where T : Enum
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • @WaiHaLee 谢谢。链接固定 (2认同)