2009-11-25 31 views
56

Nếu tôi có một lớp học với thành viên enum và tôi muốn có thể đại diện cho các tình huống mà thành viên này không được xác định, điều đó tốt hơn không?C# Enums: Nullable hoặc 'Unknown' Value?

a) Khai báo thành viên là không thể sử dụng được trong lớp bằng cách sử dụng các loại nullable. Ví dụ:

public SomeEnum? myEnum; 

b) Thêm giá trị mặc định, 'không xác định' vào điều tra. Ví dụ:

public enum SomeEnum { 
    Unknown, 
    SomeValueA, 
    SomeValueB, 
    SomeValueC, 
} 

Tôi thực sự không thể thấy bất kỳ ưu điểm/nhược điểm chính nào; nhưng có lẽ ai là người thích hợp hơn người kia?

+0

Câu hỏi này thực sự nên được gắn thẻ 'Chủ quan'. –

+23

Vâng, nếu câu hỏi có vẻ chủ quan, nó chỉ là do sự thiếu kiến ​​thức của tôi. Nếu có những lý do vững chắc tại sao người ta nên sử dụng cái kia thì nó không thực sự chủ quan. – UpTheCreek

Trả lời

58

Chắc chắn sử dụng loại giá trị có thể đặt giá trị - đó là những gì chúng dành cho. Nó nêu rõ ý định của bạn. Điều này cũng có nghĩa là bạn có thể sử dụng Enum.IsDefined (hoặc tương đương từ Unconstrained Melody nếu bạn muốn an toàn loại chung) để dễ dàng xác định liệu giá trị cụ thể có là giá trị thực mà không đáng lo ngại về giá trị "giả" hay không.

+3

Thú vị. Liên quan: Tại sao FxCop phàn nàn về các liệt kê mà không có giá trị bằng không (tức là trong các enums gán giá trị rõ ràng cho mỗi mục), gợi ý mục "Không có" có giá trị 0? Nó không có vẻ giống như thêm một nhân tạo "Không" là một giá trị "giả" như trạng thái câu trả lời của bạn, do đó là một giải pháp kém hơn? Xem: http://msdn.microsoft.com/en-us/library/ms182149 (VS.80).aspx – Pwninstein

+5

Có lẽ quy tắc FxCop cũ hơn các loại nullable? –

+2

Vâng, nó sẽ trở lại quan điểm của tôi về nếu bạn sử dụng một nullable sau đó bạn nhận được một mặc định hợp lý, đó là những gì mà quy tắc đang cố gắng để thực thi. –

2

Nếu đó là nullable, bạn sẽ nhận được nó như là một giá trị mặc định, bạn sẽ nhận được ngoại lệ nếu bạn cố gắng sử dụng nó khi null (đó là một điều tốt!)

7

Bạn chỉ cần quyết định xem bạn cần một giá trị để biểu thị các giá trị không xác định hoặc bạn cần một cách để biểu thị sự vắng mặt của bất kỳ giá trị nào.

Trong trường hợp cần phải đại diện cho các giá trị không xác định, một thành viên enum thêm âm thanh tốt như một giải pháp.

Trong trường hợp cần đại diện cho sự vắng mặt của bất kỳ giá trị nào, hãy vô hiệu hóa giá trị đó.

Xin lưu ý rằng không có gì sai khi có cả thành viên enum "không xác định" và bản thân enum không có giá trị cùng một lúc.

HTH.

15

Tôi đồng ý với archimed7592 rằng có sự khác biệt thực sự giữa giá trị vắng mặt và giá trị "Không xác định".

Ví dụ:

"loại máu của bạn là gì?"

  • Null = giá trị vắng mặt -> câu hỏi chưa được trả lời -> đặt câu hỏi

  • "Unknown" -> kiên nhẫn chỉ ra ông không biết -> để thử nghiệm trong phòng thí nghiệm cho nhóm máu

5

CNTT PHỤC VỤ!

Bill Wagner đã liệt kê một số lý do chính đáng để thêm Không xác địnhenum khi có ý nghĩa. Tôi đề nghị mà bạn tìm thấy đầy đủ các mục, nhưng đây là một bản xem trước:

Mục 8: Đảm bảo đó 0 có phải là một nhà nước hợp lệ cho loại Value

Giá trị mặc định hệ thống NET khởi đặt tất cả các đối tượng cho tất cả 0s.Không có cách nào để bạn ngăn chặn các lập trình viên khác tạo ra một thể hiện của một kiểu giá trị được khởi tạo cho tất cả các 0. Đặt giá trị mặc định cho loại của bạn.

Một trường hợp đặc biệt là enums. Không bao giờ tạo một enum không bao gồm 0 là một lựa chọn hợp lệ. Tất cả enums có nguồn gốc từ System.ValueType. Các giá trị cho bắt đầu đếm tại 0, nhưng bạn có thể sửa đổi hành vi đó ...

Hiện tại, tôi có thể chọn loại nào đó từ ComboBox hoặc không thể chọn loại nào. Tôi đang sử dụng một enum với một thuộc tính [Description("a description")] làm đối tượng được chọn. Nếu none/Unknown là một lựa chọn tự nhiên cho một enum, thì tôi sẽ sử dụng nó để biểu thị rằng không có gì được chọn. Nếu không, tôi sẽ sử dụng Nullable<MyEnum>.

0

Mọi thứ thay đổi nếu enum được gán với thuộc tính [Flags].

[Flags] 
    enum FlagsEnum 
    { 
     None = 0, 
     First = 1, 
     Second = 2, 
     Third = 4, 
     FirstAndThird = 5 
    }