2012-10-18 20 views
9

Tôi đang cố gắng viết một phương thức mở rộng cho các Enums vô hiệu.
Giống như với ví dụ này:Phương pháp mở rộng cho nullable enum

// ItemType is an enum 
ItemType? item; 
... 

item.GetDescription(); 

Vì vậy, tôi đã viết phương pháp này mà không biên dịch đối với một số lý do mà tôi không hiểu:

public static string GetDescription(this Enum? theEnum) 
{ 
    if (theEnum == null) 
     return string.Empty; 

    return GetDescriptionAttribute(theEnum); 
} 

Tôi nhận được lỗi sau trên Enum? :

chỉ loại giá trị không thể rỗng mới có thể nằm trong hệ thống.nullable

Tại sao? Enum không thể có giá trị null!

Cập nhật:

Nếu có rất nhiều sự đếm, ItemType chỉ là một ví dụ về một trong số họ.

Trả lời

17

System.Enum là một class, vì vậy chỉ cần thả ? và điều này sẽ làm việc.

(Theo "này nên làm việc", tôi có nghĩa là nếu bạn vượt qua trong một null giá trị ItemType?, bạn sẽ nhận được một nullEnum trong phương pháp này.)

public static string GetDescription(this Enum theEnum) 
{ 
    if (theEnum == null) 
     return string.Empty; 
    return GetDescriptionAttribute(theEnum); 
} 
enum Test { blah } 

Test? q = null; 
q.GetDescription(); // => theEnum parameter is null 
q = Test.blah; 
q.GetDescription(); // => theEnum parameter is Test.blah 
+0

http://msdn.microsoft.com/en-us/library/system.enum.aspx – Jacek

+0

@Jacek Ý của bạn là gì? – Rawling

+0

@ Jacek: Tôi sẽ viết điều đó, nhưng tôi đã thử nghiệm nó và nó thật đáng ngạc nhiên, hoạt động. – Jens

0

Có lẽ tốt hơn là gia tăng giá trị thêm để enum của bạn và gọi nó là rỗng :)

+1

Vâng, tôi đồng ý, một Enum với một trong các giá trị của nó "Không xác định" hoặc "Null" hoặc một cái gì đó sẽ có ý nghĩa hơn. Hoặc bạn có thể bọc enum của bạn trong một lớp học và làm cho rằng null nếu bạn thực sự muốn có một giá trị null. –

+2

Huh? Điều ngược lại chính xác là đúng - chỉ các loại giá trị có thể được sử dụng với 'Nullable '. Và làm thế nào là 'không thể tha thứ 'có liên quan? –

+0

Enum null không phải là tùy chọn. không có trong asp.net-MVC – gdoron

3

Bạn nên sử dụng các loại enum thực tế trong phương pháp chữ ký của bạn:

public static string GetDescription(this ItemType? theEnum) 

System.ValueTypeSystem.Enum không được đối xử như các kiểu giá trị (chỉ các kiểu bắt nguồn từ chúng), vì vậy chúng không có giá trị (và bạn không chỉ định chúng là nullable). Hãy thử nó:

// No errors! 
ValueType v = null; 
Enum e = null; 

Bạn cũng có thể thử chữ ký này:

public static string GetDescription<T>(this T? theEnum) where T: struct 

cũng này cho phép struct s mặc dù, trong đó có thể không phải những gì bạn muốn. Tôi nghĩ rằng tôi nhớ một số thư viện mà thêm một ràng buộc loại enum sau khi biên dịch (C# không cho phép nó) mặc dù. Chỉ cần tìm thấy nó ...

EDIT: Tìm thấy nó:

http://code.google.com/p/unconstrained-melody/

+0

Nếu có nhiều enums, 'ItemType' chỉ là một ví dụ. Tôi chắc chắn nó là hiển nhiên, xin lỗi. – gdoron

+0

Ồ, phần thứ hai bạn đã thêm câu trả lời cho câu hỏi của tôi, cảm ơn. Nhưng có cách nào để vượt qua thiết kế kỳ lạ này không? – gdoron

+0

Bạn có thể sử dụng một ràng buộc chung, nhưng C# không cho phép chỉ định enum như một ràng buộc. Xem chỉnh sửa của tôi để biết giải pháp. – Botz3000

1

Bạn chỉ có thể làm cho phương pháp mở rộng của bạn generic:

public static string GetDescription<T>(this T? theEnum) where T : struct 
{ 
    if (!typeof(T).IsEnum) 
     throw new Exception("Must be an enum."); 

    if (theEnum == null) 
     return string.Empty; 

    return GetDescriptionAttribute(theEnum); 
} 

Thật không may, bạn không thể sử dụng System.Enum trong một hạn chế chung chung, do các phương pháp khuyến nông sẽ hiển thị cho tất cả các giá trị nullable (do đó việc kiểm tra thêm).

+0

Điều này là tốt đẹp bởi vì nó tránh boxing. Bạn cũng có thể nói '! TheEnum.HasValue' nếu bạn thích. Nếu bất kỳ ai quan tâm đến ràng buộc chung cho 'System.Enum', cũng đọc [Hạn chế chung cho enums và delegate] (https://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for -enums-and-delegates.aspx). –