有人知道缺少枚举通用约束的好解决方法吗?
我想做的是这样的:我有带有组合标记值的枚举。
public static class EnumExtension
{
public static bool IsSet<T>( this T input, T matchTo )
where T:enum //the constraint I want that doesn't exist in C#3
{
return (input & matchTo) != 0;
}
}
那么我可以这样做:
MyEnum tester = MyEnum.FlagA | MyEnum.FlagB
if( tester.IsSet( MyEnum.FlagA ) )
//act on flag a
不幸的是,C# 的泛型约束没有枚举限制,只有类和结构。 C# 不将枚举视为结构(即使它们是值类型),因此我无法添加这样的扩展类型。
有人知道解决方法吗?
What I want to do is something like this: I have enums with combined flagged values.
public static class EnumExtension
{
public static bool IsSet<T>( this T input, T matchTo )
where T:enum //the constraint I want that doesn't exist in C#3
{
return (input & matchTo) != 0;
}
}
So then I could do:
MyEnum tester = MyEnum.FlagA | MyEnum.FlagB
if( tester.IsSet( MyEnum.FlagA ) )
//act on flag a
Unfortunately, C#'s generic where constraints have no enum restriction, only class and struct. C# doesn't see enums as structs (even though they are value types) so I can't add extension types like this.
Does anyone know a workaround?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我只是想添加 Enum 作为通用约束。
虽然这只是一个使用
ExtraConstraints
的小辅助方法对我来说有点太多的开销。我决定只创建一个
struct
约束并为IsEnum
添加运行时检查。 为了将变量从 T 转换为 Enum,我首先将其转换为对象。I just wanted to add Enum as a generic constraint.
While this is just for a tiny helper method using
ExtraConstraints
is a bit too much overhead for me.I decided to just just create a
struct
constraint and add a runtime check forIsEnum
. For converting a variable from T to Enum I cast it to object first.这是我刚刚编写的一些代码,它们似乎可以按照您想要的方式工作,而无需做任何太疯狂的事情。 它不仅限于设置为标志的枚举,但如果需要,总是可以进行检查。
Here's some code that I just did up that seems to work like you want without having to do anything too crazy. It's not restricted to only enums set as Flags, but there could always be a check put in if need be.
如果有人需要通用 IsSet(即时创建,可以改进),或者字符串到 Enum onfly 转换(使用下面介绍的 EnumConstraint):
如果有人仍然需要示例热来创建 Enum 编码约束:
希望这对某人有帮助。
if someone needs generic IsSet (created out of box on fly could be improved on), and or string to Enum onfly conversion (which uses EnumConstraint presented below):
If someone still needs example hot to create Enum coding constraint:
hope this helps someone.
从 C# 7.3 开始,您可以对泛型类型使用 Enum 约束:
如果要使用 Nullable 枚举,则必须保留原始结构约束:
As of C# 7.3, you can use the Enum constraint on generic types:
If you want to use a Nullable enum, you must leave the orginial struct constraint:
事实上,这是可能的,只是用了一个丑陋的把戏。
但是,它不能用于扩展方法。
如果需要,您可以为
Enums
提供一个私有构造函数和一个公共嵌套抽象继承类,其中Temp
作为Enum
,以防止非枚举的继承版本。Actually, it is possible, with an ugly trick.
However, it cannot be used for extension methods.
If you want to, you can give
Enums<Temp>
a private constructor and a public nested abstract inherited class withTemp
asEnum
, to prevent inherited versions for non-enums.您可以使用 IL Weaving 和 ExtraConstraints
允许您编写此代码
< strong>编译什么
You can achieve this using IL Weaving and ExtraConstraints
Allows you to write this code
What gets compiled
这并没有回答最初的问题,但 .NET 4 中现在有一个名为 Enum.HasFlag 执行您在示例中尝试执行的操作
This doesn't answer the original question, but there is now a method in .NET 4 called Enum.HasFlag which does what you are trying to do in your example
我这样做的方法是设置一个结构约束,然后在运行时检查 T 是否是一个枚举。 这并不能完全消除问题,但确实会在一定程度上减轻问题
The way I do it is put a struct constraint, then check that T is an enum at runtime. This doesn't eliminate the problem completely, but it does reduce it somewhat
使用原始代码,在方法内部,您还可以使用反射来测试 T 是否是枚举:
Using your original code, inside the method you can also use reflection to test that T is an enum:
从 C# 7.3 开始,现在有一种内置方法可以添加枚举约束:
来源:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
As of C# 7.3, there is now a built-in way to add enum constraints:
source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
Darren,如果类型是特定枚举,那么这将起作用 - 为了使通用枚举起作用,您必须将它们转换为整数(或更可能是 uint)来进行布尔数学运算:
Darren, that would work if the types were specific enumerations - for general enumerations to work you have to cast them to ints (or more likely uint) to do the boolean math:
编辑:这现已在 UnconstrainedMelody 的 0.0.0.2 版本中上线。
(根据我的 关于枚举约束的博客文章。为了获得独立的答案,我在下面列出了基本事实。)
最好的解决方案是等待我将其包含在 UnconstrainedMelody1 中。 这是一个库,它采用带有“假”约束的 C# 代码,
将其转换为
并通过构建后步骤
C# 代码。 编写
IsSet
应该不会太难...尽管同时满足基于Int64
和基于UInt64
的标志可能很棘手部分。 (我闻到一些辅助方法即将出现,基本上允许我将任何标志枚举视为具有UInt64
基类型。)如果您调用 ,您希望行为是什么
? 它是否应该检查所有指定的标志是否已设置? 这将是我的期望。
今晚我会在回家的路上尝试这样做......我希望能够对有用的枚举方法进行快速闪电战,以使库快速达到可用标准,然后放松一下。
编辑:顺便说一句,我不确定
IsSet
作为名称。 选项:欢迎思考。 我确信无论如何,一切都需要一段时间才能确定...
1 当然,或者将其作为补丁提交...
EDIT: This is now live in version 0.0.0.2 of UnconstrainedMelody.
(As requested on my blog post about enum constraints. I've included the basic facts below for the sake of a standalone answer.)
The best solution is to wait for me to include it in UnconstrainedMelody1. This is a library which takes C# code with "fake" constraints such as
and turns it into
via a postbuild step.
It shouldn't be too hard to write
IsSet
... although catering for bothInt64
-based andUInt64
-based flags could be the tricky part. (I smell some helper methods coming on, basically allowing me to treat any flags enum as if it had a base type ofUInt64
.)What would you want the behaviour to be if you called
? Should it check that all the specified flags are set? That would be my expectation.
I'll try to do this on the way home tonight... I'm hoping to have a quick blitz on useful enum methods to get the library up to a usable standard quickly, then relax a bit.
EDIT: I'm not sure about
IsSet
as a name, by the way. Options:Thoughts welcome. I'm sure it'll be a while before anything's set in stone anyway...
1 or submit it as a patch, of course...