2013-05-12 23 views
7

Một nhà phát triển tại nơi làm việc gần đây đã bắt đầu sử dụng một mẫu lớp thay vì enums ở những nơi mà enums thường sẽ phù hợp. Thay vào đó, ông sử dụng một cái gì đó tương tự như dưới đây:Khi nào và làm thế nào tôi nên sử dụng các lớp liệt kê thay vì enums?

internal class Suit 
{ 
    public static readonly Suit Hearts = new Suit(); 
    public static readonly Suit Diamonds = new Suit(); 
    public static readonly Suit Spades = new Suit(); 
    public static readonly Suit Clubs = new Suit(); 
    public static readonly Suit Joker = new Suit(); 
    private static Suit() 
    { 

    } 
    public static bool IsMatch(Suit lhs, Suit rhs) 
    { 
     return lhs.Equals(rhs) || (lhs.Equals(Joker) || rhs.Equals(Joker)); 
    } 
} 

lập luận của ông là nó vô hình trông giống như một điều tra, nhưng cho phép ông để chứa các phương pháp liên quan đến thù lao (như IsMatch ở trên) để được chứa bên trong liệt kê chính nó.

Anh ấy gọi đây là lớp liệt kê, nhưng đó không phải là điều tôi từng thấy trước đây. Tôi tự hỏi những lợi thế và bất lợi là gì và tôi có thể tìm thêm thông tin ở đâu?

Cảm ơn

Edit: Một ưu điểm khác ông mô tả là việc có thể để thêm một ToString cụ thể() thực hiện cho việc đếm.

+0

Vâng, bạn không thể làm điều này bằng 'enum' vì bạn không thể nhập enum vào loại phức tạp. Tôi đoán đây là lý do chính để sử dụng một cái gì đó như thế này? –

+0

Nhược điểm thực sự duy nhất (bên cạnh một số thư viện của bên thứ ba không quá hài lòng về nó) Tôi đã gặp phải là bạn không thể (trivially) làm một chuyển đổi/trường hợp trên các loại. Nhưng sau đó tôi đã không sử dụng kỹ thuật rộng rãi trong C#. –

+0

Tránh các câu lệnh chuyển đổi là điểm bán hàng chính của anh ấy. Ông đã sử dụng nó để tránh những gì ông mô tả như là báo cáo chuyển đổi nguyên khối. Đó là một điểm mặc dù nó dừng bạn sử dụng chúng ngay cả khi bạn muốn. –

Trả lời

1

Ưu điểm chính của enums là chúng về cơ bản là số nguyên với một số giá trị được đặt tên, vì vậy chúng vốn dĩ có thể di chuyển và tuần tự. Các phép toán số học và logic cũng nhanh hơn trên các enums.

Các lớp liệt kê được sử dụng khi bạn cần một giá trị mờ có thông tin trạng thái bổ sung. Ví dụ một generic Data Access Layer có thể có như một giao diện như:

 
public static class Dal 
{ 
    public static Record Query(Operation operation, Parameters parameters); 
} 

var result = Dal.Query(Operation.DoSomething, new DoSomethingParameters {...}); 

Đối với người dùng của Dal Operation chỉ là một liệt kê các hoạt động có sẵn, nhưng nó có thể chứa chuỗi kết nối, các câu lệnh SQL hoặc lưu trữ thủ tục và bất kỳ dữ liệu nào khác cần thiết bởi Dal chung.

Sử dụng "phổ biến" khác là dành cho các chế độ công khai trong hệ thống (trạng thái hoặc chiến lược). Từ góc độ người dùng, chế độ là một giá trị mờ đục, nhưng nó có thể chứa thông tin hoặc chức năng nội bộ rất quan trọng đối với việc triển khai hệ thống. Một ví dụ giả tạo:

 

public class TheSystem 
{ 
    public SystemMode Mode; 
    public void Save() 
    { 
     Mode.Save(); 
    } 
    public SystemDocument Read() 
    { 
     return Mode.Read(); 
    } 
} 

public abstract class SystemMode 
{ 
    public static SystemMode ReadOnly = new ReadOnlyMode(); 
    public static SystemMode ReadWrite = new ReadWriteMode(); 

    internal abstract void Save(); 
    internal abstract SystemDocument Read(); 

    private class ReadOnlyMode : SystemMode 
    { 
     internal override void Save() {...} 
     internal override SystemDocument Read() {...} 
    } 

    private class ReadWriteMode : SystemMode 
    { 
     internal override void Save() {...} 
     internal override SystemDocument Read() {...} 
    } 
} 


TheSystem.Mode = SystemMode.ReadOnly; 

Tôi không nghĩ rằng chỉ có một phương pháp tĩnh IsMatch đảm bảo không sử dụng enums đơn giản. Một cái gì đó rất tương tự có thể đạt được với các phương pháp mở rộng trong trường hợp này.

+0

Vì vậy, họ là một công cụ nổi tiếng có sử dụng của nó, nhưng không nên được sử dụng ở mọi nơi. Giống như hầu hết mọi thứ. Cảm ơn các ví dụ. –

1

Enums rất tốt cho thông tin trạng thái nhẹ. Ví dụ, màu sắc của bạn enum (không bao gồm màu xanh) sẽ là tốt cho truy vấn trạng thái của một đèn giao thông. Màu sắc thật cùng với toàn bộ khái niệm về màu sắc và tất cả hành lý của nó (alpha, không gian màu, vv) không quan trọng, chỉ trạng thái nào là ánh sáng. Ngoài ra, thay đổi enum của bạn một chút để thể hiện trạng thái của đèn giao thông :

[Flags()] 
public enum LightColors 
{ 
    unknown = 0, 
    red = 1, 
    yellow = 2, 
    green = 4, 
    green_arrow = 8 
} 

Tình trạng ánh sáng hiện tại có thể được thiết lập như:

LightColors c = LightColors.red | LightColors.green_arrow; 

Và truy vấn như:

if ((c & LightColors.red) == LightColors.red) 
    { 
     //Don't drive 
    } 
    else if ((c & LightColors.green_arrow) == LightColors.green_arrow) 
    { 
     //Turn 
    } 

tĩnh thành viên lớp màu sẽ có thể hỗ trợ nhiều này trạng thái không có chức năng bổ sung.

Tuy nhiên, các thành viên lớp tĩnh là tuyệt vời cho các đối tượng thường được sử dụng. Các thành viên System.Drawing.Color là những ví dụ tuyệt vời khi chúng đại diện cho một màu tên đã biết có các nhà xây dựng tối nghĩa (trừ khi bạn biết các màu hex của bạn).Nếu họ đã thực hiện như enums bạn sẽ phải làm một cái gì đó như thế này mỗi khi bạn muốn sử dụng giá trị như một màu sắc:

colors c = colors.red; 
     switch (c) 
     { 
      case colors.red: 
       return System.Drawing.Color.FromArgb(255, 0, 0); 
       break; 
      case colors.green: 
       return System.Drawing.Color.FromArgb(0,255,0); 
       break; 
     } 

Vì vậy, nếu bạn đã có một enum và thấy rằng bạn thường xuyên làm một switch/case/if/else/bất cứ điều gì để lấy được một đối tượng, bạn có thể muốn sử dụng các thành viên lớp tĩnh. Nếu bạn chỉ truy vấn trạng thái của một cái gì đó, tôi sẽ gắn bó với enums. Ngoài ra, nếu bạn phải truyền dữ liệu xung quanh trong một enums thời trang không an toàn có thể sẽ tồn tại tốt hơn so với một phiên bản serialized của đối tượng của bạn.

tham khảo hình thành một bài cũ từ diễn đàn này: When to use enums, and when to replace them with a class with static members?

+0

Bài đăng này rất giống với những gì tôi đang tìm kiếm, với một ví dụ điển hình từ khung công tác. Cảm ơn –

4

Enums chỉ tốt trong nhiều tình huống, nhưng khá nghèo ở những người khác. Thường thì tôi tìm thấy một số vấn đề với Enums:

  • Hành vi liên quan đến việc liệt kê được nằm rải rác xung quanh việc áp dụng
  • giá trị liệt kê mới đòi hỏi shotgun phẫu thuật
  • Enumerations không theo Open-Closed Nguyên tắc

Với hành vi liệt kê nằm rải rác xung quanh, chúng tôi không bao giờ có thể đưa nó trở lại loại nguồn, bởi vì các kiểu liệt kê không thể có bất kỳ hành vi nào (hoặc trạng thái cho vấn đề đó).

Mặt khác với một Enumeration Lớp:

Tất cả các biến thể của từng loại liệt kê có thể được đẩy xuống không chỉ đối với lớp liệt kê, nhưng với mỗi kiểu phụ cụ thể.

Các tính năng hoạt động tốt trong nhiều tình huống khác nhau, nhưng có thể phân tích nhanh chóng bên trong mô hình miền của bạn. Các lớp liệt kê cung cấp nhiều khả năng sử dụng giống nhau, với lợi ích bổ sung khi trở thành điểm đến cho hành vi.

Báo cáo chuyển đổi không còn cần thiết, vì tôi có thể đẩy sự thay đổi và kiến ​​thức mà nó thuộc về, quay trở lại bên trong mô hình. Nếu vì một lý do nào đó, tôi cần kiểm tra các giá trị lớp liệt kê cụ thể, tùy chọn vẫn mở cho tôi. Mẫu này không nên thay thế tất cả các bảng liệt kê, nhưng rất hay để có một giải pháp thay thế.

có thể đọc trên đó here

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