在this question中,我在enum
与[Flags]
属性之间使用xor运算符,如下所示:
[Flags]
enum QueryFlag
{
None = 0x1,
ByCustomer = 0x2,
ByProduct = 0x4,
ByDate = 0x8
}
QueryFlag flags = QueryFlag.ByCustomer | QueryFlag.ByProduct;
要添加QueryFlag,我们当然应该使用|
运算符。
flags |= QueryFlag.ByDate;
要删除一个,我对Dan Tao's answer有不同的看法。我正在使用:
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
是否包含一个项目?根据丹涛的回答,我写了一个扩展名:
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
通用更多enum
[Flags]
属性。
public static bool Contains<T>(this T flags, T flag) where T : Enum//with [Flags]
{
return (flags & (~flag)) != flags;
}
可能无法用标记的属性约束T.但即使我删除了这个约束,我也会收到编译错误operator ~ can't be applied to type T
。为什么以及如何解决?
答案 0 :(得分:0)
更好的方法可能是:
return (flags & mask) == mask;
如果mask
中设置的所有标记都设置在flags
中,则返回true。
return (flags & mask) != 0;
如果在mask
中设置了flags
中设置的任何标记,则返回true。
对于通用方法,您可以尝试将类型约束为struct
。这会将T
约束为值类型。
public static bool Contains<T>(this T flags, T mask) where T : struct
{
return (flags & mask) == mask;
}
答案 1 :(得分:0)
您的错误在于此方法:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & (~flag)) != flags;
}
只要flags
有任何(即至少一个)flag
中包含的标志,就会返回true,但我认为你想要所有
应该是:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & flag) == flag;
}
或者,您可以使用Enum.HasFlag()
来完成此操作。例如:
QueryFlag qf = ...;
if (qf.HasFlag(QueryFlag.ByCustomer))
// ...