2008-11-09 40 views
53

Trong vs2008, có thể viết một phương pháp mở rộng áp dụng cho bất kỳ điều tra nào.Phương pháp mở rộng liệt kê

Tôi biết bạn có thể viết các phương pháp mở rộng dựa trên một điều tra cụ thể, nhưng tôi muốn có thể liệt kê tất cả bằng cách sử dụng một phương pháp mở rộng duy nhất. Điều này có thể không?

Trả lời

80

Có, chỉ cần mã đối với loại cơ sở Enum, ví dụ:

public static void Something(this Enum e) 
{ 
    // code here 
} 

Các xuống bên là có thể bạn sẽ kết thúc lên làm một số công cụ khá khó chịu như việc tìm kiếm các loại cơ sở thực sử dụng Enum.GetUnderlyingType, đúc, và đi các chi nhánh xuống khác nhau tùy thuộc vào những gì các loại hình cơ bản của enum là, nhưng bạn có thể tìm thấy một số cách sử dụng tốt cho nó (ví dụ: chúng tôi có các phương pháp IsOneOfIsCombinationOf áp dụng cho tất cả các enums).

PS: Hãy nhớ khi viết phương pháp, mặc dù bị bệnh, bạn có thể sử dụng floatdouble làm loại cơ sở cho enums, do đó bạn sẽ cần một số trường hợp đặc biệt cho những giá trị đó.

+0

Các ví dụ bạn đưa ra là chính xác những gì tôi muốn làm, thậm chí cùng tên. :) –

+4

@Greg: Trong ngôn ngữ nào bạn có thể sử dụng float và double như kiểu cơ bản cho một enum? Bạn không thể trong C# - bạn nhận được lỗi CS1008: Loại byte, sbyte, ngắn, ushort, int, uint, long, hoặc ulong mong đợi –

+3

Ngôn ngữ duy nhất tôi biết là hỗ trợ nó là CIL. Tôi đã không thực sự thử nó ra để chứng minh nó bởi vì nó có vẻ như một ý tưởng chung xấu, nhưng xem bình luận của Rico gần đáy ở đây: http://en.csharp-online.net/.NET_Type_Design_Guidelines%E2%80%94Enum_Design –

18

Có, bạn có thể. Loại extenstion đích là loại Enum. Trong C#, điều này sẽ được thực hiện như:

public static void EnumExtension(this Enum e) 
{ 
} 

hay như thế này trong VB:

<Extension()> _ 
Public Sub EnumExtension(ByVal s As Enum) 
End Sub 
18

FYI Đây là một ví dụ tuyệt vời của một phương pháp Enum mở rộng mà tôi đã có thể sử dụng. Nó thực hiện một trường hợp chức năng TryParse() không nhạy cảm đối với sự đếm:

public static class ExtensionMethods 
{ 
    public static bool TryParse<T>(this Enum theEnum, string strType, 
     out T result) 
    { 
     string strTypeFixed = strType.Replace(' ', '_'); 
     if (Enum.IsDefined(typeof(T), strTypeFixed)) 
     { 
      result = (T)Enum.Parse(typeof(T), strTypeFixed, true); 
      return true; 
     } 
     else 
     { 
      foreach (string value in Enum.GetNames(typeof(T))) 
      { 
       if (value.Equals(strTypeFixed, 
        StringComparison.OrdinalIgnoreCase)) 
       { 
        result = (T)Enum.Parse(typeof(T), value); 
        return true; 
       } 
      } 
      result = default(T); 
      return false; 
     } 
    } 
} 

Bạn sẽ sử dụng nó theo cách sau đây:

public enum TestEnum 
{ 
    A, 
    B, 
    C 
} 

public void TestMethod(string StringOfEnum) 
{ 
    TestEnum myEnum; 
    myEnum.TryParse(StringOfEnum, out myEnum); 
} 

Dưới đây là hai trang web mà tôi đã đến thăm để giúp đưa ra mã này :

Case Insensitive TryParse for Enums

Extension methods for Enums

+8

Giống như chú thích, từ .net 4 trở đi có Enum.TryParse mất quá tải để chỉ định độ nhạy trường hợp: http://msdn.microsoft.com/en-us/ library/dd991317% 28v = vs.100% 29.aspx – KevD

9

Đây là một ví dụ khác - IMHO đẹp hơn việc tạo và khởi tạo biến tạm thời.

public static class ExtensionMethods 
{ 
    public static void ForEach(this Enum enumType, Action<Enum> action) 
    { 
     foreach (var type in Enum.GetValues(enumType.GetType())) 
     { 
      action((Enum)type); 
     } 
    } 
} 

public enum TestEnum { A,B,C } 
public void TestMethod() 
{ 
    default(TestEnum).ForEach(Console.WriteLine); 
} 
+0

Bạn vẫn đang tạo một cá thể tạm thời của enum trong 'default (TestEnum)', mặc dù một trong đó là ẩn danh và lập tức thu gom rác. Điều đáng nói là các phương thức mở rộng chỉ đơn giản là không làm việc mà không có một thể hiện của những gì đang được mở rộng, vì vậy gần nhất mà chúng ta có thể nhận là khởi tạo Kiểu của chính enum và có một phương thức mở rộng loại đó. Xem http://stackoverflow.com/questions/2422113/extension-method-on-enumeration-not-instance-of-enumeration cho một cách thú vị để hoàn thành việc này. – MushinNoShin

4

Bạn cũng có thể thực hiện phương pháp chuyển đổi như sau:

public static class Extensions 
{ 
    public static ConvertType Convert<ConvertType>(this Enum e) 
    { 
     object o = null; 
     Type type = typeof(ConvertType); 

     if (type == typeof(int)) 
     { 
      o = Convert.ToInt32(e); 
     } 
     else if (type == typeof(long)) 
     { 
      o = Convert.ToInt64(e); 
     } 
     else if (type == typeof(short)) 
     { 
      o = Convert.ToInt16(e); 
     } 
     else 
     { 
      o = Convert.ToString(e); 
     } 

     return (ConvertType)o; 
    } 
} 

Đây là một cách sử dụng ví dụ:

int a = MyEnum.A.Convert<int>(); 
+0

Tôi nghĩ mọi 'Enum' thực hiện' IConvertible'. – ja72

2

Đôi khi có một nhu cầu để chuyển đổi từ một enum khác, dựa trên tên hoặc giá trị của enum. Dưới đây là cách thực hiện điều này một cách độc đáo với các phương pháp mở rộng:

enum Enum1 { One = 1, Two = 2, Three = 3 }; 
enum Enum2 { Due = 2, Uno = 1 }; 
enum Enum3 { Two, One }; 

Enum2 e2 = Enum1.One.ConvertByValue<Enum2>(); 
Enum3 e3 = Enum1.One.ConvertByName<Enum3>(); 
Enum3 x2 = Enum1.Three.ConvertByValue<Enum3>(); 

public static class EnumConversionExtensions 
{ 
    public static T ConvertByName<T>(this Enum value) 
    { 
     return (T)Enum.Parse(typeof(T), Enum.GetName(value.GetType(), value)); 
    } 

    public static T ConvertByValue<T>(this Enum value) 
    { 
     return (T)((dynamic)((int)((object)value))); 
    } 
} 
1

Ví dụ khác về cách tạo phần mở rộng Enum - nhưng lần này nó trả về kiểu enum đầu vào.

public static IEnumerable<T> toElementsCollection<T>(this T value) where T : struct, IConvertible 
    { 
     if (typeof(T).IsEnum == false) throw new Exception("typeof(T).IsEnum == false"); 

     return Enum.GetValues(typeof(T)).Cast<T>(); 
    } 

Ví dụ về sử dụng:

public enum TestEnum { A,B,C }; 

TestEnum.A.toElementsCollection(); 
Các vấn đề liên quan