【发布时间】:2010-09-20 03:22:04
【问题描述】:
在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;
}
也就是说,如果从flags中删除flags后flags没有改变,我们就知道flags不在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。为什么以及如何解决?
【问题讨论】:
-
您希望 .Contains(QueryFlag.ByDate | QueryFlag.ByCustomer) 在设置其中一个标志时返回 true,还是只设置两个标志?
标签: c# .net generics enums extension-methods