2009-08-17 31 views
34

Một nhà phát triển đồng nghiệp đề nghị chúng tôi lưu trữ một số ngày trong tuần như chuỗi gồm 7 ký tự 1 và 0, tức là "1000100" cho Thứ Hai và Thứ Sáu. Tôi ưa thích (và mạnh mẽ đề xuất) một giải pháp với một hoạt động bit enum và bitwise, tôi nghĩ rằng đó là một cách sạch hơn để làm điều này, và nó sẽ được dễ dàng hơn để hiểu cho các nhà phát triển khác.Cờ enum & bitwise hoạt động so với "chuỗi bit"

[Flags()] 
    public enum Weekdays : int 
    { 
    Monday = 1, 
    Tuesday = 2, 
    Wednesday = 4, 
    Thursday = 8, 
    Friday = 16, 
    Saturday = 32, 
    Sunday = 64 
    } 

Tuy nhiên, khi tôi bắt đầu để thực hiện một giải pháp mẫu, tôi nhận ra rằng có lẽ cách tiếp cận chuỗi đơn giản là dễ dàng hơn sau khi tất cả: Chắc chắn là bit chuỗi là rõ ràng hơn “17” nếu bạn chỉ nhìn vào dữ liệu. Và tôi tìm ra C# Bitwise hoạt động phản trực giác và cực kỳ tiết:

Weekdays workDays = Weekdays.Monday | Weekdays.Tuesday; 
if ((workDays & Weekdays.Monday) == Weekdays.Monday) 
{...} 

Tất nhiên điều này có thể được bao bọc độc đáo vào phương pháp khuyến nông, nhưng sau đó chúng tôi đột nhiên kết thúc với ít nhất cùng một số dòng mã như với chuỗi giải pháp, và tôi khó có thể tranh luận mã bitwise dễ đọc hơn.

Điều đó đang được nói, tôi vẫn sẽ đi với một cờ enum và bitwise hoạt động. Các lợi ích chính tôi có thể nghĩ đến là

  • Hiệu suất tốt hơn
  • Ít không gian cần thiết cho việc lưu trữ

Vì vậy, làm thế nào để bán các giải pháp Bitwise với các đồng nghiệp của tôi? Tôi có nên không? Những lợi ích khác của việc sử dụng phương pháp này trên dây là gì? Sau khi hoàn thành dự án mẫu, tôi thấy rằng nhóm vẫn chọn giải pháp dựa trên chuỗi. Tôi cần một số đối số tốt hơn/mạnh hơn. Tại sao bạn nên sử dụng Flags enums thay vì bit-string đơn giản?

+4

Không giải quyết được câu hỏi của bạn, nhưng tại sao tạo ra enum của riêng bạn cho điều này khi đã có 'System.DayOfWeek'? –

+8

Các giá trị enums System.DayOfWeek là 0 đến 6, không phải bội số của 2 (1, 2, 4, 8, 16, 32 và 64) mà tôi cần thực hiện các thao tác bitwise (AFAIK). Bên cạnh đó, MONDAY là ngày đầu tiên trong tuần. :) –

+0

Để giảm tiết, bạn có thể viết: 'if ((workDays & Weekdays.Monday)! = 0)' –

Trả lời

40

Lợi ích của việc sử dụng Flags enum:

Phủ định của việc sử dụng Flags enum: đại diện dữ liệu

  • cho con người khó có thể hiểu được (ví dụ như những gì cờ được thiết lập cho 17)


Lợi ích của việc sử dụng chuỗi bit:

  • dễ dàng cho các lập trình viên để xem những bit được thiết lập trong chuỗi

Phủ định của việc sử dụng chuỗi các bit:

  • phi tiêu chuẩn tiếp cận
  • Harder hiểu cho các lập trình viên quen thuộc với thiết kế của bạn
  • Có thể dễ dàng đặt giá trị "rác" hơn (ví dụ:stringValue = "Sunday")
  • Không cần chuỗi tạo
  • Không cần chuỗi phân tích cú pháp
  • công việc phát triển bổ sung
  • reinventing the wheel (nhưng thậm chí không phải là một bánh xe tròn)


Làm thế nào quan trọng là nó thực sự để có thể nhìn vào chuỗi bit để xem những gì được thiết lập? Nếu thật khó để biết rằng 17 là thứ Hai và thứ Sáu, bạn luôn có thể sử dụng máy tính và chuyển đổi thành nhị phân. Hoặc thêm một số loại biểu diễn chuỗi cho "hiển thị" (hoặc gỡ lỗi) sử dụng. Nó không phải là rằng khó khăn. Nó cũng dường như với tôi rằng nếu bạn đang đi để làm cho chuỗi bit tiếp cận rắn sau đó bạn sẽ cần phải làm khá một chút đóng gói để đưa nó lên đến một mức độ trừu tượng mà Flags enum đã cung cấp. Nếu cách tiếp cận này chỉ đơn giản là thao tác chuỗi các bit trực tiếp thì điều đó sẽ khó đọc (và hiểu) và có thể dễ bị lỗi.

ví dụ: bạn có thể sẽ thấy điều này:

days = "1000101"; // fixed bug where days were incorrectly set to "1010001" 
+2

Bạn có thể tận dụng tối đa cả hai thế giới bằng cách sử dụng 0x0001 cho Chủ Nhật, 0x0010 cho Thứ Hai, 0x0100 cho Thứ Ba, v.v. Bằng cách này, khi bạn chuyển giá trị thành hex, bạn sẽ có được danh sách người có thể đọc được trong ngày. . –

+0

Bạn có hai "Phủ định sử dụng cờ enum", thứ hai phải là "Phủ định sử dụng chuỗi bit @ –

+0

@Alexey: Cảm ơn ... đã sửa lúc này. –

0

Ngạc nhiên cả hai phương pháp đó đều giống nhau; chỉ có phương pháp cờ là rõ ràng hơn.

Cá nhân tôi đi với các cờ (mặc dù có khả năng, tùy thuộc vào kiểu máy của bạn, tốt hơn hết là lưu trữ danh sách dưới dạng Danh sách chống lại bất kỳ ai đang giữ nó).

- Sửa

Và để được rõ ràng, hiệu suất thực sự không cần phải là một cân nhắc cho những gì bạn đang làm, tôi nghĩ vậy. Vì vậy, chỉ cần đi với dễ đọc nhất. (Trong đó, IMHO, là các cờ được đặt tên).

+0

Tôi đồng ý, hiệu suất kém quan trọng (mặc dù đây có thể là vấn đề ở đây, xem xét cách tiếp cận mà họ đang chọn). Tôi cũng nghĩ rằng đó là dễ đọc hơn, ít nhất là khi bạn sử dụng một tập hợp các phương thức mở rộng nhỏ cho các hoạt động bitwise (trong đó, một cách rõ ràng, là quá nhiều cho họ để grok). –

+0

Điều quan trọng là họ học bitwise hoạt động anyway. Tôi sẽ sử dụng trường hợp rất đơn giản này như một cách để dạy cho họ, cá nhân. –

+0

Yup, do đó ứng dụng mẫu rất đơn giản - mà tôi hy vọng sẽ dạy cho họ điều này. Tôi cần bao gồm một vài đối số siêu rắn với mẫu đó ... –

1

Câu hỏi nên tập trung vào việc liệu mắt người có thực sự nhìn thấy giá trị được lưu trữ này hay không. Nếu vậy, một định dạng có thể đọc được của con người rõ ràng là quan trọng (mặc dù nếu đúng như vậy, tôi sẽ đưa ra một lý lẽ cho một thứ gì đó lớn hơn, giống như một mảng tên thật). Tuy nhiên, ít nhất là trong tất cả các ứng dụng tôi từng tạo, loại dữ liệu này đi vào một trường nhỏ ở đâu đó và không bao giờ được nhìn thấy nữa, ngoại trừ mã C# - có nghĩa là bitflags chắc chắn là đơn giản nhất - chúng hầu hết mọi người có thể đọc được trong mã. Đồng nghiệp của bạn thực sự muốn viết một trình phân tích cú pháp chuỗi ánh xạ 0 và 1 cho các giá trị thay vì sử dụng được xây dựng trongđược sử dụng trong 40+ năm ý tưởng về các hoạt động bitwise?

+0

Tôi không nghĩ rằng đề nghị là để thực sự sử dụng một chuỗi * cho phương pháp 'thay thế' là nó? Bởi vì đó chỉ là điên rồ, tôi đồng ý. Có lẽ tôi đã hiểu sai. –

+0

@silky đó là cách tôi đọc: "là chuỗi gồm 7 ký tự 1 và 0, nghĩa là" 1000100 "cho Thứ Hai và Thứ Sáu." điên thực sự –

+0

"Các đồng nghiệp của bạn thực sự muốn viết một trình phân tích cú pháp chuỗi ánh xạ 0 và 1 cho các giá trị thay vì sử dụng tích hợp và được sử dụng trong 40+ năm về các hoạt động bitwise?" ... câu trả lời buồn và trung thực? Vâng, đó là sự điên rồ mà tôi chứng kiến. –

0

Phương pháp cờ là thành ngữ (nghĩa là những gì người lập trình có kinh nghiệm làm và quen với việc xem và làm, ít nhất bằng ngôn ngữ C/C++/C#).

+0

Tôi hoàn toàn đồng ý: Tôi chỉ cần kẻ giết người-đối số để biến chúng. –

6

Tạo lớp học có thể giữ kết hợp các ngày trong tuần.Bên trong lớp, bạn có thể đại diện cho dữ liệu theo cách, nhưng tôi chắc chắn sẽ đi cho một bảng liệt kê cờ hơn là một chuỗi. Bên ngoài lớp bạn chỉ sử dụng các giá trị enum, và logic thực tế được đóng gói trong lớp.

Cái gì như:

[Flags] 
public enum Days { 
    Monday = 1, 
    Tuesday = 2, 
    Wednesday = 4, 
    Thursday = 8, 
    Friday = 16, 
    Saturday = 32, 
    Sunday = 64, 
    MondayToFriday = 31, 
    All = 127, 
    None = 0 
} 

public class Weekdays { 

    private Days _days; 

    public Weekdays(params Days[] daysInput) { 
     _days = Days.None; 
     foreach (Days d in daysInput) { 
     _days |= d; 
     } 
    } 

    public bool Contains(Days daysMask) { 
     return (_days & daysMask) == daysMask; 
    } 

    public bool Contains(params Days[] daysMasks) { 
     Days mask = Days.None; 
     foreach (Days d in daysMasks) { 
     mask |= d; 
     } 
     return (_days & mask) == mask; 
    } 

} 

Cách sử dụng Ví dụ:

Weekdays workdays = new Weekdays(Days.MondayToFriday); 
if (workdays.Contains(Days.Monday, Days.Wednesday)) { 
    ... 
} 
+0

Tôi nghĩ bạn đã hiểu sai câu hỏi ... Câu hỏi không phải là "Làm thế nào tôi có thể thực hiện điều này bằng cách sử dụng enums?" Câu hỏi này giống như "Tôi có thể sử dụng các đối số nào để thuyết phục đồng nghiệp của mình rằng việc triển khai dựa trên enum là phù hợp nhất?" – Alderath

+1

@Alderath: Không.Câu trả lời của tôi chỉ là việc thực hiện nên được đóng gói trong một lớp để nó không thực sự quan trọng như thế nào các giá trị được đại diện. – Guffa

+0

@Guffa Cảm ơn ví dụ nhỏ gọn. – zionpi

23

Bạn không nên tạo datastructures phi tiêu chuẩn để thay thế một cấu trúc dữ liệu tiêu chuẩn (trong trường hợp này, dayOfWeek BUILTIN enum) . Thay vào đó, hãy mở rộng cấu trúc hiện có. Điều này làm việc về cơ bản giống như phương pháp bit cờ bạn đang nói về.

namespace ExtensionMethods 
{ 
    public static class Extensions 
    { 
     /* 
     * Since this is marked const, the actual calculation part will happen at 
     * compile time rather than at runtime. This gives you some code clarity 
     * without a performance penalty. 
     */ 
     private const uint weekdayBitMask = 
      1 << Monday 
      | 1 << Tuesday 
      | 1 << Wednesday 
      | 1 << Thursday 
      | 1 << Friday; 
     public static bool isWeekday(this DayOfWeek dayOfWeek) 
     { 
      return 1 << dayOfWeek & weekdayBitMask > 0; 
     } 
    } 
} 

Bây giờ bạn có thể làm như sau:

Thursday.isWeekday(); // true 
Saturday.isWeekday(); // false 
+0

Đơn giản, thông minh. Tôi thích cách tiếp cận mở rộng. Tiện ích mở rộng cho Enumerations rất mạnh mẽ. – AMissico

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