Kei*_*ith 87 .net c# enums flags
我想要做的是这样的:我有枚举标记值的枚举.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
那么我可以这样做:
MyEnum tester = MyEnum.FlagA | MyEnum.FlagB
if( tester.IsSet( MyEnum.FlagA ) )
//act on flag a
Run Code Online (Sandbox Code Playgroud)
不幸的是,C#的通用,其中约束没有枚举限制,只有类和结构.C#不会将枚举视为结构(即使它们是值类型),因此我无法像这样添加扩展类型.
有没有人知道解决方法?
Jon*_*eet 48
编辑:这是现在的UnconstrainedMelody版本0.0.0.2.
(根据我在博客文章中关于枚举约束的要求.为了获得独立答案,我已经在下面列出了基本事实.)
最好的解决方案是等待我将其包含在UnconstrainedMelody 1中.这是一个带有C#代码的库,其中包含"假"约束
where T : struct, IEnumConstraint
Run Code Online (Sandbox Code Playgroud)
把它变成了
where T : struct, System.Enum
Run Code Online (Sandbox Code Playgroud)
通过postbuild步骤.
它不应该太难写IsSet
......虽然迎合了既Int64
基于和UInt64
基于标志可能是棘手的部分.(我闻到了一些辅助方法,基本上允许我处理任何标志枚举,就好像它有一个基本类型UInt64
.)
如果你打电话,你想要的行为是什么?
tester.IsSet(MyFlags.A | MyFlags.C)
Run Code Online (Sandbox Code Playgroud)
?它应该检查是否设置了所有指定的标志?那是我的期望.
我会在今晚回家的路上尝试这样做...我希望快速闪现有用的枚举方法,让图书馆快速达到可用的标准,然后放松一下.
编辑:IsSet
顺便说一下,我不确定这个名字.选项:
欢迎思考.不管怎么说,我确定它还有一段时间才能结束.
1,或者将其作为补丁提交,当然......
Iva*_*rić 17
从C#7.3开始,现在有一种内置的方法来添加枚举约束:
public class UsingEnum<T> where T : System.Enum { }
Run Code Online (Sandbox Code Playgroud)
来源:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
Ron*_*nie 16
Darren,如果类型是特定的枚举,它将起作用 - 对于一般的枚举工作,你必须将它们转换为int(或更可能是uint)来进行布尔数学运算:
public static bool IsSet( this Enum input, Enum matchTo )
{
return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0;
}
Run Code Online (Sandbox Code Playgroud)
实际上,这可能是一个丑陋的伎俩.但是,它不能用于扩展方法.
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.IsSet<DateTimeKind>("Local")
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以Enums<Temp>
使用Temp
as 提供私有构造函数和公共嵌套抽象继承类Enum
,以防止非枚举的继承版本.
您可以使用IL Weaving和ExtraConstraints实现此目的
允许您编写此代码
public class Sample
{
public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
{
}
public void MethodWithEnumConstraint<[EnumConstraint] T>()
{
}
}
Run Code Online (Sandbox Code Playgroud)
什么被编译
public class Sample
{
public void MethodWithDelegateConstraint<T>() where T: Delegate
{
}
public void MethodWithEnumConstraint<T>() where T: struct, Enum
{
}
}
Run Code Online (Sandbox Code Playgroud)
从 C# 7.3 开始,您可以对泛型类型使用 Enum 约束:
public static TEnum Parse<TEnum>(string value) where TEnum : Enum
{
return (TEnum) Enum.Parse(typeof(TEnum), value);
}
Run Code Online (Sandbox Code Playgroud)
如果要使用 Nullable 枚举,则必须保留原始结构约束:
public static TEnum? TryParse<TEnum>(string value) where TEnum : struct, Enum
{
if( Enum.TryParse(value, out TEnum res) )
return res;
else
return null;
}
Run Code Online (Sandbox Code Playgroud)