当前位置: 首页 > 编程语言 > C#

C#3.0中“特殊类”枚举的泛型类型约束是否有解决方法?

时间:2023-04-10 16:27:28 C#

C#3.0中“特殊类”枚举的泛型类型约束是否有解决方法?更新:请参阅此问题的底部以获取C#解决方法。嗨,考虑以下扩展方法:publicstaticboolHasFlags(thisTvalue,Tflags)whereT:System.Enum{//...}如您所知,这会在编译时抛出错误,因为类通常不会允许从System.Enuminheritance继承。问题是使用enum关键字指定的任何枚举实际上都是从System.Enuminheritance继承的,因此上面的代码非常适合将扩展方法限制为仅枚举。现在明显的解决方法是使用Enum而不是T,但是你失去了泛型类型的好处:MyEnume;e.HasFlags(MyOtherEnum.DoFunkyStuff);上面的代码将在使用泛型类型时抛出编译时错误,而它只能使用枚举类型抛出运行时错误(如果我实现它就会发生这种情况。)是否有任何编译器选项可用于关闭约束检查,或者还有其他一些漂亮的方法可以做到这一点吗?在建议之前,我想说我不会使用whereT:struct或其他whereT:struct,从那以后你可以做一些奇怪的事情,比如123.HasFlags(456)。我很困惑为什么这个错误存在...这与您使用whereT:System.Object时遇到的问题相同,但为此您有whereT:class...为什么不在whereT:enum中?C#解决方法JonSkeet已经开始研究一个库,该库编译带有IEnumConstraint约束的类,然后用System.Enumpost-build替换它。我相信,这是迄今为止最接近解决这个问题的人。请参阅:如果此解决方法不可行,则必须将库编写为C++/CLI代码,这不限制可用于泛型类型约束的内容(请参阅下面答案中的代码。)编辑:现在通过ildasm/ilasm支持该库:UnconstrainedMelody。C#团队的成员之前曾表示,他们希望能够支持whereT:Enum和whereT:Delegate,但它的优先级永远不够高。(我不确定首先限制的原因是什么,诚然...)C#中最实用的解决方法是:publicstaticboolHasFlags(thisTvalue,Tflags)whereT:struct{if(!(valueisEnum)){thrownewArgumentException();}//...}这会丢失对“enum-ness”的编译时检查,但会检查您是否在两个地方使用相同的类型。当然,它也有检查的执行时间惩罚。第一次调用后,您可以通过使用泛型嵌套类型来避免执行时间损失,该类型的实现将在静态构造函数中抛出异常:publicstaticboolHasFlags(thisTvalue,Tflags)whereT:struct{if(!(值是Enum)){thrownewArgumentException();}returnEnumHelper.HasFlags(value,flags);}privateclassEnumHelperwhereT:struct{staticEnumHelper(){if(!typeof(Enum).IsAssignableFrom(typeof(T)){thrownewInvalidOperationException();//或类似的东西}}internalstaticHasFlags(Tvalue,Tflags){...}}正如Greco提到的,您可以在C++中执行此操作/在CLI中编写方法,然后从C#中引用类库是另一种选择。这里有一个解决方法。实际上,这可能是一个丑陋的把戏。但是,它不适用于扩展方法。publicabstractclassEnumswhereTemp:class{publicstaticTEnumParse(stringname)whereTEnum:struct,Temp{return(TEnum)Enum.Parse(typeof(TEnum),name);}}publicabstractclassEnums:Enums{}Enums.Parse("Local")如果愿意,您可以为Enums提供一个私有构造函数和一个公共嵌套抽象继承类,其中Temp是Enum以防止非枚举继承版本。我无法抗拒参与C++解决方案,并且自从它开始工作后,我想我会与其他人分享它!这是C++代码(我的C++很生疏,所以请指出任何错误,特别是参数是如何定义的):#include"stdafx.h"usingnamespaceSystem;使用命名空间System::Runtime::CompilerServices;namespaceBlixt{namespaceUtilities{[Extension]publicrefclassEnumUtilityabstractsealed{public:generic其中T:valueclass,Enum[Extension]staticboolHasFlags(Tvalue,Tflags){__int64mask=Convert::ToInt64(flags);返回(转换::ToInt64(值)&掩码)==掩码;}};用于测试的C#代码(控制台应用程序):usingSystem;使用Blixt.Utilities;namespaceBlixt.Playground{[Flags]publicenumColors:byte{Black=0,Red=1,Green=2,Blue=4}[Flags]publicenumTastes:byte{Nothing=0,Sour=1,Sweet=2,Bitter=4,Salty=8}classProgram{staticvoidMain(string[]args){颜色c=Colors.Blue|颜色.红色;Console.WriteLine("绿色和蓝色?{0}",c.HasFlags(Colors.Green|Colors.Red));Console.WriteLine("蓝色?{0}",c.HasFlags(Colors.Blue));Console.WriteLine("绿色?{0}",c.HasFlags(Colors.Green));Console.WriteLine("红色和蓝色?{0}",c.HasFlags(Colors.Red|Colors.Blue));//编译错误://Console.WriteLine("Sour?{0}",c.HasFlags(Tastes.Sour));Console.WriteLine("按任意键退出...");控制台.ReadKey(true);您可以使用ILWeaving和ExtraConstraints实现此目的,允许您编写此代码对于C#3.0中“特殊类”枚举的泛型类型约束?如果分享的内容对你有用,需要了解更多C#学习教程,希望你多多关注——publicstaticboolHasFlags(thisTvalue,Tflags)whereT:System.Enum{//...}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处: