Методы расширения перечисления
в vs2008 можно ли написать методы расширения, которые будут применяться к любому перечислению.
Я знаю, что вы можете написать методы расширения против конкретного перечисления, но я хочу иметь возможность каждого перечисления, используя один метод расширения. Это возможно?
7 ответов:
да, просто код от базы
Enum
тип, например,public static void Something(this Enum e) { // code here }
недостатком является то, что вы, вероятно, в конечном итоге делаете некоторые довольно неприятные вещи, такие как поиск реального базового типа с помощью
Enum.GetUnderlyingType
, литье и спуск по разным ветвям в зависимости от того, какой базовый тип перечисления, но вы можете найти для него хорошее применение (например, у нас естьIsOneOf
иIsCombinationOf
методы, которые применяются ко всем перечислениям).PS: помните при написании метода, что, хотя и болен посоветовал, вы можете использовать
float
иdouble
в качестве базовых типов для перечислений, поэтому вам понадобятся некоторые специальные случаи для этих, а также беззнаковых значений.
Да, вы можете. Целевой тип расширения имеет тип
Enum
. В C# это делается так:public static void EnumExtension(this Enum e) { }
или вот так в VB:
<Extension()> _ Public Sub EnumExtension(ByVal s As Enum) End Sub
FYI вот отличный пример метода расширения перечисления, который я смог использовать. Он реализует нечувствительную к регистру функцию TryParse () для перечислений:
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; } } }
вы бы использовали его следующим образом:
public enum TestEnum { A, B, C } public void TestMethod(string StringOfEnum) { TestEnum myEnum; myEnum.TryParse(StringOfEnum, out myEnum); }
вот два места, которые я посетил, чтобы помочь придумать этот код:
вот еще один пример-также лучше IMHO, чем необходимость создавать и инициализировать временную переменную.
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); }
вы также можете реализовать метод преобразования следующим образом:
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; } }
пример использования:
int a = MyEnum.A.Convert<int>();
иногда возникает необходимость конвертировать из одного перечисления в другое, основываясь на имени или значении перечисления. Вот как это можно сделать красиво с помощью методов расширения:
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))); } }
еще один пример создания расширения перечисления-но на этот раз он возвращает тип входного перечисления.
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>(); }
пример использования:
public enum TestEnum { A,B,C }; TestEnum.A.toElementsCollection();