Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何知道项目在枚举中?_C#_.net_Generics_Enums_Extension Methods - Fatal编程技术网

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的方法!这正是我想要的。谢谢