2010-04-17 25 views
34

Hãy tưởng tượng chúng ta có một enum:Chuyển đổi một số nguyên cho một loại enum đóng hộp duy nhất được biết trong thời gian chạy

enum Foo { A=1,B=2,C=3 } 

Nếu loại được biết đến tại thời gian biên dịch, một dàn diễn viên trực tiếp có thể được sử dụng để thay đổi giữa enum- loại và các loại cơ bản (thường int):

static int GetValue() { return 2; } 
... 
Foo foo = (Foo)GetValue(); // becomes Foo.B 

và boxing này đưa ra một hộp loại Foo:

object o1 = foo; 
Console.WriteLine(o1.GetType().Name); // writes Foo 

(và trên thực tế, bạn có thể hộp như Foo và Unbox như int, hoặc hộp như int và Unbox như Foo khá hạnh phúc)

Tuy nhiên (vấn đề); nếu kiểu enum chỉ được biết ở những thứ thời gian chạy thì ... phức tạp hơn. Nó rõ ràng là tầm thường để hộp nó như là một int - nhưng tôi có thể hộp nó như Foo? (Lý tưởng nhất là không sử dụng generics và MakeGenericMethod, mà sẽ là xấu xí). Convert.ChangeType ném một ngoại lệ. ToStringEnum.Parse hoạt động, nhưng là khủng khiếp không hiệu quả.

Tôi có thể xem các giá trị đã xác định (Enum.GetValues hoặc Type.GetFields), nhưng điều đó rất khó cho [Flags] và thậm chí không cần quay trở lại kiểu đầu tiên (không khó, may mắn).

Nhưng; có trực tiếp hơn để lấy giá trị của kiểu cơ bản đúng cho một hộp kiểu enum không, trong đó kiểu chỉ được biết khi chạy?

Trả lời

60

Tôi nghĩ phương pháp Enum.ToObject sẽ làm những gì bạn muốn.

Type type= typeof(Foo); 
object o1 = Enum.ToObject(type,GetValue()); 
+2

Làm thế nào các | $ (* &% $ (Tôi đã bỏ lỡ điều đó! Cảm ơn, đó là chính xác những gì tôi muốn. –

+3

Dễ dàng bỏ lỡ. Có vẻ như một tên phương pháp khủng khiếp. Một cái gì đó như 'Enum.FromValue' có thể có –

8

Chỉ muốn thêm cái gì đó để @aaronb's answer: Tôi đã phải làm điều này rất cho một số mã tự động lập bản đồ và phát hiện ra rằng tôi cần phải làm một số kiểm tra để thực hiện các công việc mã với nhiều loại tùy ý. Đặc biệt, các giá trị null và enums rỗng sẽ cho bạn đau đầu.

Mã hết sức rõ ràng nhất mà tôi có vào lúc này là thế này:

static object CastBoxedValue(object value, Type destType) 
{ 
    if (value == null) 
     return value; 

    Type enumType = GetEnumType(destType); 
    if (enumType != null) 
     return Enum.ToObject(enumType, value); 

    return value; 
} 

private static Type GetEnumType(Type type) 
{ 
    if (type.IsEnum) 
     return type; 

    if (type.IsGenericType) 
    { 
     var genericDef = type.GetGenericTypeDefinition(); 
     if (genericDef == typeof(Nullable<>)) 
     { 
      var genericArgs = type.GetGenericArguments(); 
      return (genericArgs[0].IsEnum) ? genericArgs[0] : null; 
     } 
    } 
    return null; 
} 

Nếu bạn không bao giờ có thể có một loại nullable sau đó chỉ cần bỏ qua điều này. :)

+0

Những suy nghĩ vô giá, nhưng thực sự tôi đã loại bỏ những thứ như 'Nullable ', 'Danh sách ' etc ngược dòng này. –

+0

'Nullable.GetUnderlyingType' có thể đơn giản hơn việc kiểm tra các đối số chung. – Craig

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