C# 我如何知道项目在枚举中?
在中,我在C# 我如何知道项目在枚举中?,c#,.net,generics,enums,extension-methods,C#,.net,Generics,Enums,Extension Methods,在中,我在enum和[Flags]属性之间使用xor运算符,如下所示: [Flags] enum QueryFlag { None = 0x1, ByCustomer = 0x2, ByProduct = 0x4, ByDate = 0x8 } QueryFlag flags = QueryFlag.ByCustomer | QueryFlag.ByProduct; 要添加QueryFlag,我们当然应该使用|操作符 flags |= QueryFlag.ByDate; 要删
enum
和[Flags]
属性之间使用xor运算符,如下所示:
[Flags]
enum QueryFlag
{
None = 0x1,
ByCustomer = 0x2,
ByProduct = 0x4,
ByDate = 0x8
}
QueryFlag flags = QueryFlag.ByCustomer | QueryFlag.ByProduct;
要添加QueryFlag,我们当然应该使用|
操作符
flags |= QueryFlag.ByDate;
要删除一个,我有一个不同的方法。我正在使用:
flags ^= QueryFlag.ByProduct;
当他使用时:
flags &= ~QueryFlag.ByProduct;
显然,他的回答是正确的,很容易理解。我认为我犯了一个错误。但经过深思熟虑,我发现:
a,b a^b a&(~b)
0,0 0 0
0,1 1 0 //the difference
1,0 1 1
1,1 0 0
现在我知道我错了<代码>^在尝试删除一个不存在的项目时出错
QueryFlag q = QueryFlag.ByCustomer | QueryFlag.ByDate;
//try to remove QueryFlag.ByProduct which doesn't exist in q
q ^ QueryFlag.ByProduct //equals to add ByProduct to q, wrong!
q & (~QueryFlag.ByProduct) // q isn't changed, remain the original value. correct!
但这里我有另一个问题:我如何知道q
是否包含一项?根据Dan Tao的回答,我写了一个扩展:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & (~flag)) != flags;
}
也就是说,若从标志中删除标志后标志未更改,则我们知道标志不在标志中!以下情况似乎是正确的:
(QueryFlag.ByProduct | QueryFlag.ByDate).Contains(QueryFlag.None) //false
(QueryFlag.ByProduct | QueryFlag.ByDate).Contains(QueryFlag.ByDate) //true
但事实上:
(QueryFlag.ByProduct | QueryFlag.ByDate).Contains(QueryFlag.ByDate | QueryFlag.ByCustomer) //true, but I suppose it's false
我知道这是错误的原因,我如何改进它?这是第一个问题。
第二:我想使.Contains
泛型为带有[Flags]
属性的更多enum
public static bool Contains<T>(this T flags, T flag) where T : Enum//with [Flags]
{
return (flags & (~flag)) != flags;
}
publicstaticbool包含(这个T标志,T标志),其中T:Enum//with[flags]
{
返回(flags&(~flag))!=标志;
}
可能不可能用标记的属性约束T。但是,即使我删除了这个约束,我也会得到一个编译错误,它说,
operator~不能应用于类型t
。为什么以及如何解决?更好的方法可能是:
return (flags & mask) == mask;
如果在flags
中设置了mask
中设置的所有标志,则返回true
return (flags & mask) != 0;
如果在mask
中设置的任何标志在flags
中设置,则返回true
return (flags & mask) != 0;
至于泛型方法,您可以尝试将类型约束为struct
。这将T
限制为值类型
public static bool Contains<T>(this T flags, T mask) where T : struct
{
return (flags & mask) == mask;
}
publicstaticbool包含(这个T标志,T掩码),其中T:struct
{
返回(标志和掩码)=掩码;
}
您的错误在于此方法:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & (~flag)) != flags;
}
每当标志
包含标志
中包含的任何标志(即至少一个)时,此项返回true,但我认为您需要所有标志
应改为:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & flag) == flag;
}
或者,您也可以使用Enum.HasFlag()。例如:
QueryFlag qf = ...;
if (qf.HasFlag(QueryFlag.ByCustomer))
// ...
如果设置了其中一个标志,您希望.Contains(QueryFlag.ByDate | QueryFlag.ByCustomer)返回true,还是仅设置了这两个标志?现在我理解了您对第一个问题的两个答案。非常感谢。但是对于第二个问题,编写约束where T:int
是不正确的,因为int
不能是where
的约束。我仍然在考虑类型限制。似乎可以将struct指定为约束,从而将T约束为值类型。请参阅编辑后的答案。答案仍然错误。您不能在t
类型上使用&
或=
。我可以谦虚地建议您在发布代码之前尝试编译它吗?哦!我不知道HasFlag的方法!这正是我想要的。谢谢