2011-11-02 6 views
10

tôi đang cố gắng ra các tính năng HasFlags mới, và đã tự hỏi nếu sau nên công việc:Nên "hay" làm việc với .Net4 Hasflags: enum.HasFlag (AccessRights.Read | AccessRights.Write)

enum.HasFlag (AccessRights.Read | AccessRights.Write)

... bởi vì nó dường như không ...

DBAccessRights rights = (DBAccessRights)permission.PermissionFlags; 
    if (rights.HasFlag(DBAccessRights.WikiMode)) 
    { 
    // works 
    } 


    if (rights.HasFlag(DBAccessRights.WikiMode | DBAccessRights.CreateNew)) 
    { 
    // Doesn't work  
    } 

    DBAccessRights flags = DBAccessRights.WikiMode | DBAccessRights.CreateNew; 
    if (rights.HasFlag(flags)) 
    { 
    // Doesn't work 
    } 

Trả lời

20

Cho the documentation, tôi hy vọng rằng trả về true nếu giá trị có cả hai trong số các cờ đó.

Nếu bạn muốn nó để kiểm tra xem giá trị của bạn có hoặc của những lá cờ, bạn sẽ cần

value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write) 

Nếu đó là không tốt có thể đọc được đủ cho bạn, bạn có thể muốn xem xét dự án Unconstrained Melody của tôi . Nó như vậy sẽ xảy ra rằng đã có các chức năng bạn muốn (như phương pháp khuyến nông trong Flags.cs):

// Same as value.HasFlag(AccessRights.Read | AccessRights.Write) 
value.HasAll(AccessRights.Read | AccessRights.Write) 

// Same as value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write) 
value.HasAny(AccessRights.Read | AccessRights.Write) 

Những sẽ làm cho nó rõ ràng hơn, IMO. Họ cũng muốn tránh boxing, và được typesafe :)

+0

Quyền anh có giải thích ghi chú hiệu suất ở cuối tài liệu không? – LamonteCristo

+1

@ makerofthings7: Có thể - thật khó để nói chắc chắn. Thật thú vị khi đo lường sự khác biệt về hiệu suất giữa khung công tác và triển khai của tôi :) –

+0

@LamonteCristo Phương pháp này cũng phải thực hiện kiểm tra kiểu trước khi hủy hộp. Họ muốn ném một 'ArgumentException' nếu bạn chuyển một tham chiếu của một kiểu sai. Tôi tự hỏi nếu kiểm tra loại được thực hiện một lần nữa trong unboxing. Chúng ta có thể kiểm tra bytecode hoặc nguồn C#. –

3

Nhà điều hành | là bitwise hoặc. Nó có nghĩa là nếu Read là 1 và Write là 2, thì giá trị Read | Write là 3 (xem biểu diễn nhị phân của nó). Vì vậy, HasFlag chỉ trả về true nếu biến số enum của bạn có cả haiReadWrite được đặt.

18

Từ MSDN:

Phương pháp HasFlag trả về kết quả của Boolean biểu thức sau đây.

thisInstance Và flag = cờ

Đối với một lá cờ phức tạp như AccessRights.Read | AccessRights.Write, điều này sẽ kiểm tra xem tất cả các "chứa" cờ có mặt.

Bạn có thể muốn kiểm tra xem bất kỳ của lá cờ có mặt, trong trường hợp này bạn có thể làm:

myAccessRights & (AccessRights.Read | AccessRights.Write) != 0 
+0

Tôi bị xé rách giữa việc chấp nhận điều này và câu trả lời của Jon Skeet. Đó là cách tối ưu để đạt được mục tiêu của tôi. Câu trả lời của ông giải thích những gì tôi đã làm sai. – LamonteCristo

1

Ngoài ra, bạn chỉ có thể đảo ngược thứ tự của biểu thức:

//returns true - a bit easier on the eye 
(AccessRights.Read | AccessRights.Write).HasFlag(myAccessRights) 

Điều này sẽ trả về true nếu bạn có hoặc Đọc | Ghi truy cập.Đó sẽ là chức năng tương đương với:

//also returns true - as per @Ani's answer 
myAccessRights & (AccessRights.Read | AccessRights.Write) != 0 

EDIT

Như đã chỉ ra trong các ý kiến, Khái niệm đầu tiên sẽ trở thành sự thật nếu myAccessRights là trống rỗng, và false nếu myAccessRights có nhiều hơn chỉ là Đọc và Viết .

+0

Nó trả về true nếu myAccessRights không có cờ đặt những gì không đúng. Nhưng dù sao. Giống như cách tiếp cận này – AnzeR

+0

Nó không tương đương về mặt chức năng trừ khi bạn giả định rằng Đọc và Ghi là các cờ duy nhất được xác định trong AccessRights - mà bạn không nên cho dù nó là đúng sự thật. Biểu thức đầu tiên sẽ trả về false nếu myAccessRights có bất kỳ cờ nào được đặt ngoài đọc hoặc viết. – Jelly

+0

Cảm ơn bạn đã chỉ ra @AnzeR – AaronHS