2017-02-14 83 views
0

我有以下enum问题与枚举为标志

[Flags] 
public enum Status { Nominal, Modified, DirOneOnly, DirTwoOnly, DirOneNewest, DirTwoNewest } 

我试图看到Modified位是否已被设置为true,曾尝试以下方法:

if(_stateFlags.HasFlag(Status.Modified)) 
{ 
    //DoStuff 
} //Found out why this doesn't work after reading docs. 

if((_stateFlags & Status.Modified) == Status.Modified) 
{ 
    //DoStuff 
} 

后者是我进一步研究的方法led我相信会工作。但是,当我做_stateFlags = Status.DirTwoOnly上述声明仍然似乎评估为true这真的让我感到困惑。

我在做一些根本性的错误吗?

+0

你给了它[Flags]属性,但枚举没有明确的值。 (int)Status = 3可能是DirTwoOnly或可能是Nominal |改性。你必须给它们编号,使它们不重叠。所以1,2,4,8,16等 –

+0

谢谢@HansPassant我假设他们默认为两个权力。我的错。 –

+0

您可能会考虑是否值得定义自己的结构,该结构仍然占用4个字节,但具有像“IsModified”等自定义方法。必须对位进行位算术以确定其含义,使得应该读取的代码像语义 - “是否修改了状态?“ - 阅读更多的机制 - ”是位数组的第三位开启了吗?“ –

回答

6

You need to define the enum constants as powers of two.

[Flags] 
public enum Status 
{ 
    Nominal = 1, 
    Modified = 2, 
    DirOneOnly = 4, 
    DirTwoOnly = 8, 
    DirOneNewest = 16, 
    DirTwoNewest = 32 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Status s = new Status(); 
     s |= Status.Modified; 
     if (s.HasFlag(Status.Modified)) 
     { 
      Console.WriteLine("Modified!"); 
     } 
    } 
} 
+0

哦,我认为这是默认的,我会接受时间限制通过。谢谢! –

+0

属性只是元数据和ca不要改变像这样的枚举的默认行为,但是对于像这样的标志有一个直观的机制是很好的。 – TVOHM

+0

这将是很好,没有理由(我意识到)会停止编译器能够改变它的方式基于属性的方式。 –

1

代码:

[Flags] 
public enum Status { Nominal, Modified, DirOneOnly, DirTwoOnly, DirOneNewest, DirTwoNewest } 

等于:

[Flags] 
public enum Status 
{ 
    Nominal  = 0, // in bits: ... 0000 0000 
    Modified  = 1, //    0000 0001 
    DirOneOnly = 2, //    0000 0010 
    DirTwoOnly = 3, //    0000 0011 **common bit with Modified state ** 
    DirOneNewest = 4, 
    DirTwoNewest = 5, 

}

所以当别人说,你需要使用的动力2为enum val UE的。

+0

感谢@apocolypse,我假设通过使用[Flags]属性,它从1递增到2的幂。 –

7

你有几个解答你的问题的答案,解释什么是错的。我会建议完全采取不同的方法。

标志枚举有一个非常90年代的感觉给他们;如果你认为他们看起来像是在COM中进行互操作的话,并且如果你认为COM枚举看起来像是为了与20世纪70年代的代码混搭代码兼容,那么你是对的。

我不会在新代码中将此逻辑表示为枚举。我会花时间写一个清晰地表达我的实际语义的自定义结构。

struct Status 
{ 
    public static readonly Status None = default(Status); 
    private Status(int bits) { this.bits = bits; } 
    private int bits; 
    private const int NominalBitMask = 0b0001; 
    private const int ModifiedBitMask = 0b0010; 
    ... etc ... 
    public bool IsNominal => (this.bits & NominalBitMask) != 0; 
    public Status WithNominal(bool f) => 
    new Status(f ? (this.bits | NominalBitMask) : (this.bits & ~NominalBitMask)); 
    ... etc ... 

现在你可以使用它像:

Status status = Status.None.WithNominal(true).WithModified(myFile.IsModified); 
... 
if (status.IsModified) ... 

难道这更多的工作在前面?当然,这大约需要20分钟的时间。但是,你再也不会犯任何错误。你有一个结构可以独立于使用它的逻辑进行测试。你的代码看起来像它的意思。你永远不用担心某个人将一个整数转换为你的枚举类型,并使其充满无稽之谈。您可以将自定义逻辑放入您的类型中;假设例如有三值标志 - 真,假或空,例如 - 这些在标志枚举中很难做到,但是你可以在自定义类型中轻松添加逻辑。等等。

+0

你会推荐为非标志枚举做这个吗?或者这会是矫枉过正? (假设不需要为该类型添加任何方法或属性)。 –