2011-10-24 8 views
15

Tôi thường nhìn thấy và sử dụng enums với các thuộc tính gắn liền với thực hiện một số điều cơ bản như cung cấp một tên hiển thị hoặc mô tả:"Enum là đối tượng giàu có bất biến": đây có phải là mô hình chống không?

public enum Movement { 
    [DisplayName("Turned Right")] 
    TurnedRight, 
    [DisplayName("Turned Left")] 
    [Description("Execute 90 degree turn to the left")] 
    TurnedLeft, 
    // ... 
} 

Và đã có một tập hợp các phương pháp khuyến nông để hỗ trợ các thuộc tính:

public static string GetDisplayName(this Movement movement) { ... } 
public static Movement GetNextTurn(this Movement movement, ...) { ... } 

Theo mẫu này, các thuộc tính hiện tại hoặc tùy chỉnh bổ sung có thể được áp dụng cho các trường để thực hiện những việc khác. Nó gần như là nếu enum có thể làm việc như các loại giá trị liệt kê đơn giản nó là gì và như một đối tượng giá trị bất biến phong phú hơn với một số lĩnh vực:

public class Movement 
{ 
    public int Value { get; set; } // i.e. the type backing the enum 
    public string DisplayName { get; set; } 
    public string Description { get; set; } 
    public Movement GetNextTurn(...) { ... } 
    // ... 
} 

Bằng cách này, nó có thể "đi" như một đơn giản trường trong quá trình tuần tự hóa, được so sánh nhanh chóng, v.v. Tuy nhiên, hành vi có thể được "nội bộ hóa" (ala OOP).

Điều đó nói rằng, tôi nhận ra điều này có thể được coi là chống mẫu. Đồng thời một phần của tôi cho rằng điều này hữu ích đủ để chống có thể quá nghiêm ngặt.

+4

Bạn đang hỏi xem có nên sử dụng mẫu này ở những nơi mà bạn sẽ không sử dụng enum không? Đó là một mô hình tuyệt vời để kết hợp siêu dữ liệu với các giá trị enum.Nó không tuyệt vời như một sự thay thế cho các lớp học. –

+0

Nó có thể được coi là "lạm dụng" ngôn ngữ; gần giống như sử dụng 'động' tất cả thời gian khi không được bảo hành chẳng hạn. – Kit

+1

Không chính xác về điểm (do đó nhận xét), nhưng tôi có những hiểu lầm về việc mã hóa văn bản được hiển thị trong một thuộc tính - hoặc bất cứ nơi nào gần một lớp thực thể, cho vấn đề đó. Đối với một điều, tôi nghĩ rằng nó thô bạo vi phạm "sự lo lắng của mối quan tâm" và cho người khác, không có cách nào rõ ràng để bản địa hóa nó. Than ôi, MS dường như khuyến khích loại điều này, vì vậy có lẽ tôi ra ngoài ăn trưa. –

Trả lời

6

Tôi cho rằng đây là một mẫu kém trong C# đơn giản vì hỗ trợ ngôn ngữ cho việc khai báo và truy cập các thuộc tính bị tê liệt; chúng không có nghĩa là lưu trữ nhiều dữ liệu. Đó là một nỗi đau để tuyên bố thuộc tính với các giá trị không tầm thường, và đó là một nỗi đau để có được giá trị của một thuộc tính. Ngay khi bạn muốn một cái gì đó từ xa thú vị gắn liền với enum của bạn (như một phương thức tính toán một cái gì đó trên enum, hoặc một thuộc tính có chứa một kiểu dữ liệu không nguyên thủy), bạn cần phải cấu trúc lại nó cho một lớp hoặc đặt một thứ khác vào một số nơi ngoài băng. Nó không thực sự khó khăn hơn để thực hiện một lớp bất biến với một số trường hợp tĩnh giữ cùng một thông tin, và theo ý kiến ​​của tôi, nó là thành ngữ hơn.

+0

Nó không khó, không, về mặt * tuyên bố * của một enum so với một đối tượng bất biến, giàu có, và có nỗi đau cho người thực hiện phong phú, nhưng về * sử dụng * thì sao? Mặc dù điểm của bạn trên * thành ngữ * ngồi tốt với tôi. – Kit

+0

Điểm tốt về cách viết mã thành ngữ. Bạn luôn luôn muốn viết mã mà chơi tốt đẹp với ngôn ngữ/khuôn khổ mà nó sống. – FMM

5

Tôi muốn nói đó là mẫu chống. Đây là lý do tại sao. Hãy lấy enum hiện tại của bạn (tước các thuộc tính cho ngắn gọn ở đây):

public enum Movement 
{ 
    TurnedRight, 
    TurnedLeft, 
    Stopped, 
    Started 
} 

Bây giờ, giả sử nhu cầu mở rộng là chính xác hơn một chút; nói, một sự thay đổi trong tiêu đề và/hoặc tốc độ, biến một "lĩnh vực" trong "pseudo-class" của bạn thành hai:

public sealed class Movement 
{ 
    double HeadingDelta { get; private set; } 
    double VelocityDelta { get; private set; } 
    // other methods here 
} 

Vì vậy, bạn có một enum hệ thống hóa mà hiện nay đã được chuyển đổi thành một lớp học bất biến bởi vì bây giờ bạn đang theo dõi hai thuộc tính trực giao (nhưng vẫn không thay đổi) thực sự thuộc về nhau trong cùng một giao diện. Bất kỳ mã nào mà bạn đã viết chống lại "enum giàu" của bạn bây giờ đã được gutted và làm lại đáng kể; trong khi đó, nếu bạn bắt đầu với nó như một lớp học, bạn có thể sẽ có ít việc phải làm hơn.

Bạn phải hỏi mã sẽ được duy trì theo thời gian như thế nào và nếu enum giàu có có thể duy trì dễ dàng hơn lớp học hay không. Cá cược của tôi là nó sẽ không thể duy trì được nhiều hơn. Ngoài ra, như mquander chỉ ra, cách tiếp cận dựa trên lớp học là thành ngữ hơn trong C#.

Điều gì đó khác cũng cần xem xét. Nếu đối tượng là bất biến và là struct thay vì class, bạn sẽ nhận được cùng một ngữ nghĩa theo giá trị và chênh lệch không đáng kể trong kích thước tuần tự hóa và kích thước thời gian chạy của đối tượng như bạn làm với enum.

+0

Tôi đã tham gia điều này trước và không thể đồng ý nhiều hơn. –