在这个问题中,我使用异或运算符来处理带有
为添加一个查询标记,我们应该使用
现在我知道了我的错误。当您尝试删除一个不存在的项目时,
也就是说,如果在从flags中移除flag后,flags没有发生变化,那么我们知道flag不在flags中!当以下情况时,这个结论是正确的:
但事实上:
[Flags]
属性的enum
,具体如下:[Flags]
enum QueryFlag
{
None = 0x1,
ByCustomer = 0x2,
ByProduct = 0x4,
ByDate = 0x8
}
QueryFlag flags = QueryFlag.ByCustomer | QueryFlag.ByProduct;
为添加一个查询标记,我们应该使用
|
运算符。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
是否包含一个项目?根据丹·陶的答案,我编写了一个扩展:
public static bool Contains(this QueryFlag flags, QueryFlag flag)
{
return (flags & (~flag)) != flags;
}
也就是说,如果在从flags中移除flag后,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;
}
可能无法使用标记属性来约束 T。但是,即使我删除此约束,仍会出现编译错误,提示“operator ~ 无法应用于类型 T”。为什么会出现这种情况,如何解决?