2009-06-23 36 views
96

Đôi khi khi đọc mã C# của người khác, tôi thấy một phương thức sẽ chấp nhận nhiều giá trị enum trong một tham số. Tôi luôn nghĩ nó khá gọn gàng, nhưng chưa bao giờ nhìn vào nó.Làm thế nào để bạn vượt qua nhiều giá trị enum trong C#?

Vâng, bây giờ tôi nghĩ rằng tôi có thể có một nhu cầu cho nó, nhưng không biết làm thế nào để

  1. thiết lập chữ ký phương pháp để chấp nhận điều này
  2. làm việc với các giá trị trong phương pháp
  3. xác định enum

để đạt được loại điều này.


Trong trường hợp đặc biệt của tôi, tôi muốn sử dụng các System.DayOfWeek, được định nghĩa là:

[Serializable] 
[ComVisible(true)] 
public enum DayOfWeek 
{ 
    Sunday = 0, 
    Monday = 1, 
    Tuesday = 2, 
    Wednesday = 3, 
    Thursday = 4, 
    Friday = 5,  
    Saturday = 6 
} 

Tôi muốn để có thể vượt qua một hoặc nhiều các giá trị dayOfWeek đến phương pháp của tôi. Tôi có thể sử dụng enum cụ thể này không? Làm cách nào để tôi thực hiện 3 điều được liệt kê ở trên?

+1

Như đã đề cập dưới đây, bạn có thể sử dụng một Flags enum.Bạn có thể muốn kiểm tra [Các ins and outs của C# enums] (http://www.codeducky.org/ins-outs-c-enums/), trong đó có thêm thông tin về làm việc với Flags enums. – ChaseMedallion

Trả lời

151

Khi bạn xác định enum, chỉ cần gán nó với [Flags], đặt giá trị thành lũy thừa là hai, và nó sẽ hoạt động theo cách này.

Không có thay đổi nào khác ngoài việc chuyển nhiều giá trị vào một hàm.

Ví dụ:

[Flags] 
enum DaysOfWeek 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64 
} 

public void RunOnDays(DaysOfWeek days) 
{ 
    bool isTuesdaySet = (days & DaysOfWeek.Tuesday) == DaysOfWeek.Tuesday; 

    if (isTuesdaySet) 
     //... 
    // Do your work here.. 
} 

public void CallMethodWithTuesdayAndThursday() 
{ 
    this.RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); 
} 

Để biết thêm chi tiết, xem MSDN's documentation on Enumeration Types.


Chỉnh sửa để bổ sung cho câu hỏi.

Bạn sẽ không thể sử dụng enum đó là, trừ khi bạn muốn làm điều gì đó như chuyển nó thành mảng mảng/bộ sưu tập/params. Điều đó sẽ cho phép bạn chuyển nhiều giá trị. Cú pháp cờ yêu cầu Enum được chỉ định là cờ (hoặc để khống chế ngôn ngữ theo cách mà nó không được thiết kế).

+3

WOW ... bạn đã nhanh lên! –

+9

Tôi nghĩ nếu bạn muốn làm việc này, các giá trị cần phải được định nghĩa là quyền hạn của hai, một bit duy nhất cho mỗi giá trị. Điều xảy ra là bạn vượt qua theo bitwise OR của các giá trị trong tham số, bạn có thể kiểm tra bằng cách sử dụng bitwise AND operation. Nếu bạn không chăm sóc xác định các giá trị như, ví dụ, 1,2,4,8 vv, bạn sẽ có vấn đề. –

+1

Chỉ cần đặt thuộc tính Flags một mình không hoạt động tự động. Tôi vừa thử nó. –

0

Something của thiên nhiên này sẽ hiển thị những gì bạn đang tìm kiếm:

[Flags] 
public enum SomeName 
{ 
    Name1, 
    Name2 
} 

public class SomeClass() 
{ 
    public void SomeMethod(SomeName enumInput) 
    { 
     ... 
    } 
} 
+3

Sẽ không hoạt động nếu không chỉ định các giá trị bằng quyền hạn của 2. –

21

Tôi thứ hai câu trả lời của ông Reed. Tuy nhiên, khi tạo enum, bạn phải xác định các giá trị cho mỗi thành viên enum để nó tạo ra một loại trường bit. Ví dụ:

[Flags] 
public enum DaysOfWeek 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64, 

    None = 0, 
    All = Weekdays | Weekend, 
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday, 
    Weekend = Sunday | Saturday, 
    // etc. 
} 
+1

Nó sẽ giúp bạn nếu bạn cần kiểm tra giá trị DaysOfWeek, ví dụ nếu bạn đang đọc một giá trị được lưu trữ trong cơ sở dữ liệu. Ngoài ra, nó cung cấp tài liệu tốt hơn cho các lập trình viên khác, vì một số ngày liệt kê trong tuần bắt đầu từ thứ hai thay vì chủ nhật. – Jacob

+3

Để rõ ràng và bảo trì, tôi sẽ viết 'Tất cả' enum của bạn là "Chủ nhật | Thứ Hai | Thứ Ba | Thứ Tư | Thứ Năm | Thứ Sáu | Thứ Bảy" ... và sử dụng ký hiệu tương tự cho 'Các ngày trong tuần' và 'Cuối tuần'. –

+0

Điểm tốt. Đó là tốt hơn. – Jacob

2
[Flags] 
    public enum DaysOfWeek{ 


     Sunday = 1 << 0, 
     Monday = 1 << 1, 
     Tuesday = 1 << 2, 
     Wednesday = 1 << 3, 
     Thursday = 1 << 4, 
     Friday = 1 << 5, 
     Saturday = 1 << 6 
    } 

gọi các phương pháp trong định dạng này

methodname (DaysOfWeek.Tuesday | DaysOfWeek.Thursday);

Thực hiện một phương pháp EnumToArray để có được những lựa chọn thông qua

private static void AddEntryToList(DaysOfWeek days, DaysOfWeek match, List<string> dayList, string entryText) { 
      if ((days& match) != 0) { 
       dayList.Add(entryText); 
      } 
     } 

     internal static string[] EnumToArray(DaysOfWeek days) { 
      List<string> verbList = new List<string>(); 

      AddEntryToList(days, HttpVerbs.Sunday, dayList, "Sunday"); 
      AddEntryToList(days, HttpVerbs.Monday , dayList, "Monday "); 
      ... 

      return dayList.ToArray(); 
     } 
+3

Thú vị nhưng không cần thiết. –

+0

Không trả lời câu hỏi. "Trong tình huống cụ thể của tôi, tôi muốn sử dụng System.DayOfWeek" –

+0

Cảm ơn, Robert, nhưng bạn thực sự không phải chỉ ra điều này trên mọi câu trả lời. –

9
[Flags] 
public enum DaysOfWeek 
{ 
    Mon = 1, 
    Tue = 2, 
    Wed = 4, 
    Thur = 8, 
    Fri = 16, 
    Sat = 32, 
    Sun = 64 
} 

Bạn cần phải xác định những con số, và tăng chúng như thế này bởi vì nó được lưu trữ các giá trị trong một thời trang trên bit.

Sau đó chỉ cần xác định phương pháp của bạn để tận enum này

public void DoSomething(DaysOfWeek day) 
{ 
    ... 
} 

và gọi nó là làm cái gì đó như

DoSomething(DaysOfWeek.Mon | DaysOfWeek.Tue) // Both Monday and Tuesday 

Để kiểm tra xem một trong những giá trị enum đã được bao gồm kiểm tra chúng bằng các hoạt động Bitwise như

public void DoSomething(DaysOfWeek day) 
{ 
    if ((day & DaysOfWeek.Mon) == DaysOfWeek.Mon) // Does a bitwise and then compares it to Mondays enum value 
    { 
    // Monday was passed in 
    } 
} 
+0

Không trả lời câu hỏi. "Trong tình huống cụ thể của tôi, tôi muốn sử dụng System.DayOfWeek" –

+0

Nhưng đó chính xác là những gì tôi đang tìm kiếm. Vì vậy, cảm ơn anyway. – Tillito

3

Đánh dấu enum của bạn bằng thuộc tính [Flags]. Cũng đảm bảo rằng tất cả các giá trị của bạn là loại trừ lẫn nhau (hai giá trị không thể thêm lên đến tương đương khác) như 1,2,4,8,16,32,64 trong trường hợp của bạn

[Flags] 
public enum DayOfWeek 
{ 
Sunday = 1, 
Monday = 2, 
Tuesday = 4, 
Wednesday = 8, 
Thursday = 16, 
Friday = 32,  
Saturday = 64 
} 

Khi bạn có một phương thức chấp nhận một en day DayOfWeek sử dụng bitwise hoặc toán tử (|) để sử dụng nhiều thành viên với nhau. Ví dụ:

MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday) 

Để kiểm tra xem thông số có chứa một thành viên cụ thể, sử dụng Bitwise điều hành (&) với thành viên bạn đang kiểm tra cho.

if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday) 
Console.WriteLine("Contains Sunday"); 
+0

Không trả lời câu hỏi. "Trong tình huống cụ thể của tôi, tôi muốn sử dụng System.DayOfWeek" –

2

Reed Copsey là chính xác và tôi sẽ thêm vào bài đăng gốc nếu có thể, nhưng tôi không thể để tôi phải trả lời thay thế.

Nguy hiểm khi sử dụng [Flags] trên bất kỳ enum cũ nào. Tôi tin rằng bạn phải thay đổi rõ ràng các giá trị enum thành lũy thừa của hai khi sử dụng cờ, để tránh xung đột trong các giá trị. Xem số guidelines for FlagsAttribute and Enum.

0

Với sự giúp đỡ của các câu trả lời được đăng tải và những:

  1. FlagsAttribute Class (Nhìn vào sự so sánh của việc sử dụng và không sử dụng [Flags] thuộc tính)
  2. Enum Flags Attribute

tôi cảm thấy như Tôi hiểu nó khá tốt.

Cảm ơn.

11

Trong tình huống cụ thể của tôi, tôi sẽ thích sử dụng System.DayOfWeek

Bạn không thể sử dụng System.DayOfWeek như một liệt kê [Flags] bởi vì bạn không kiểm soát được nó. Nếu bạn muốn có một phương pháp mà chấp nhận nhiều DayOfWeek sau đó bạn sẽ phải sử dụng các từ khóa params

void SetDays(params DayOfWeek[] daysToSet) 
{ 
    if (daysToSet == null || !daysToSet.Any()) 
     throw new ArgumentNullException("daysToSet"); 

    foreach (DayOfWeek day in daysToSet) 
    { 
     // if(day == DayOfWeek.Monday) etc .... 
    } 
} 

SetDays(DayOfWeek.Monday, DayOfWeek.Sunday); 

Nếu không, bạn có thể tạo riêng [Flags] liệt kê của bạn như được nêu bởi nhiều phản ứng khác và sử dụng so sánh Bitwise.

+1

Tôi không biết tại sao tôi không nghĩ đến các thông số. Điều đó sẽ rất hữu ích cho việc sử dụng enums không phải là bitfields. –

63

Tôi nghĩ rằng giải pháp thanh lịch hơn là sử dụng HasFlag():

[Flags] 
    public enum DaysOfWeek 
    { 
     Sunday = 1, 
     Monday = 2, 
     Tuesday = 4, 
     Wednesday = 8, 
     Thursday = 16, 
     Friday = 32, 
     Saturday = 64 
    } 

    public void RunOnDays(DaysOfWeek days) 
    { 
     bool isTuesdaySet = days.HasFlag(DaysOfWeek.Tuesday); 

     if (isTuesdaySet) 
     { 
      //... 
     } 
    } 

    public void CallMethodWithTuesdayAndThursday() 
    { 
     RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); 
    } 
+5

Điều này có thể thực hiện từ Framework 4.0 trở đi. – Tillito

Các vấn đề liên quan