如何在C#中比较标志?
我下面有一个标志枚举。
[Flags] public enum FlagTest { None = 0x0, Flag1 = 0x1, Flag2 = 0x2, Flag3 = 0x4 }
我无法使if语句的评估结果为true。
FlagTest testItem = FlagTest.Flag1 | FlagTest.Flag2; if (testItem == FlagTest.Flag1) { // Do something, // however This is never true. }
我如何才能做到这一点?
解决方案
回答
对于位运算,我们需要使用按位运算符。
这应该可以解决问题:
if ((testItem & FlagTest.Flag1) == FlagTest.Flag1) { // Do something, // however This is never true. }
编辑:修复了我的检查是否退回到C / C ++方式的问题(感谢Ryan Farley指出了这一点)
回答
if ((testItem & FlagTest.Flag1) == FlagTest.Flag1) { // Do something }
(testItem&FlagTest.Flag1)
是按位AND运算。
FlagTest.Flag1
等同于带有OP枚举的001
。现在让我们说testItem
具有Flag1和Flag2(所以按位是101):
001 &101 ---- 001 == FlagTest.Flag1
回答
if((testItem & FlagTest.Flag1) == FlagTest.Flag1) { ... }
回答
试试这个:
if ((testItem & FlagTest.Flag1) == FlagTest.Flag1) { // do something }
基本上,代码会询问是否设置两个标志都与设置一个标志相同,这显然是错误的。如果上面的代码被置位,则上面的代码将仅保留Flag1的位置,然后将该结果与Flag1进行比较。
回答
我设置了一个扩展方法来做到这一点:相关问题。
基本上:
public static bool IsSet( this Enum input, Enum matchTo ) { return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0; }
然后,我们可以执行以下操作:
FlagTests testItem = FlagTests.Flag1 | FlagTests.Flag2; if( testItem.IsSet ( FlagTests.Flag1 ) ) //Flag1 is set
顺便说一句,我用于枚举的约定对于标准是单数,对于标志是复数。这样,我们就可以从枚举名称中知道它是否可以容纳多个值。
回答
关于编辑。我们无法实现。我建议我们将所需的内容包装到另一个类(或者扩展方法)中,以更接近所需的语法。
IE。
public class FlagTestCompare { public static bool Compare(this FlagTest myFlag, FlagTest condition) { return ((myFlag & condition) == condition); } }
回答
在.NET 4中,有一个新方法Enum.HasFlag。这使我们可以编写:
if ( testItem.HasFlag( FlagTest.Flag1 ) ) { // Do Stuff }
IMO更具可读性。
.NET源表明这与接受的答案具有相同的逻辑:
public Boolean HasFlag(Enum flag) { if (!this.GetType().IsEquivalentTo(flag.GetType())) { throw new ArgumentException( Environment.GetResourceString( "Argument_EnumTypeDoesNotMatch", flag.GetType(), this.GetType())); } ulong uFlag = ToUInt64(flag.GetValue()); ulong uThis = ToUInt64(GetValue()); // test predicate return ((uThis & uFlag) == uFlag); }
回答
对于那些无法想象被接受的解决方案正在发生什么的人
(这是),
if ((testItem & FlagTest.Flag1) == FlagTest.Flag1) { // Do stuff. }
" testItem"(根据问题)定义为
testItem = flag1 | flag2 = 001 | 010 = 011
然后,在if语句中,比较的左侧是
(testItem & flag1) = (011 & 001) = 001
还有完整的if语句(如果在testItem
中设置了flag1
,则计算结果为true),
(testItem & flag1) == flag1 = (001) == 001 = true
回答
另一条建议...永远不要对值为" 0"的标志进行标准的二进制检查。我们对此标志的检查将始终为true。
[Flags] public enum LevelOfDetail { [EnumMember(Value = "FullInfo")] FullInfo=0, [EnumMember(Value = "BusinessData")] BusinessData=1 }
如果对FullInfo二进制检查输入参数,则会得到:
detailLevel = LevelOfDetail.BusinessData; bool bPRez = (detailLevel & LevelOfDetail.FullInfo) == LevelOfDetail.FullInfo;
bPRez将始终为true,并且ANYTHING&0 always == 0。
相反,我们应该只检查输入值是否为0:
bool bPRez = (detailLevel == LevelOfDetail.FullInfo);