короткий ответ, да. В этом конкретном случае вы можете рассмотреть возможность использованияTimeSpan
Джодрелл
1
Использование методов расширения в перечислении заставит меня почувствовать себя грязным. Создайте класс для инкапсуляции того, что необходимо. Сделайте перечисление как можно более простым. Если вам нужна дополнительная логика, связанная с ним, создайте класс Duration, который предоставляет день, неделю, месяц, а также содержит любую другую логику, которая была бы в методе расширения.
Джейсон Эванс,
2
Мне нравятся методы расширения enum для групп флагов. Я предпочитаю, если оговорки к примеру Day.IsWorkday()через (Day & Days.Workday) > 0с Days.Workdayопределяется как Monday | Tuesday ... | Friday. Первый вариант, на мой взгляд, более понятен, и в нем реализовано именно второе.
Методы расширения позволяют писать методы для существующих классов таким образом, чтобы другие люди в вашей команде могли их обнаружить и использовать. Учитывая, что перечисления являются такими же классами, как и любые другие, неудивительно, что вы можете их расширить, например:
Я думаю, что перечисления - не лучший выбор в целом, но, по крайней мере, это позволяет вам централизовать часть обработки switch / if и немного их абстрагировать, пока вы не сможете сделать что-то лучше. Не забудьте также проверить, что значения находятся в диапазоне.
Вы можете прочитать больше здесь, на Microsft MSDN.
Я считаю, что комментарий «перечисления - зло» неуместен, но имеет реальную основу. Я действительно считаю, что перечисления могут быть проблемой, поскольку они как бы привязывают вас к определенным контекстам и поведению.
Эд Швем
1
Перечисления в C # - отстой, потому что он компилируется и запускается:Duration d = 0;
Грэм,
16
Given that enums are classesнет, это не классы.
Winger
1
Я использую такого рода расширения только в том случае, если речь идет непосредственно о перечислении, например о днях недели и методах расширения IsWeekday (), IsWeekendday (). Но классы предназначены для инкапсуляции поведения, поэтому, если нужно инкапсулировать много или сложных поведений, класс, вероятно, лучше. Если он ограниченный и базовый, я лично нахожу расширения в перечислениях в порядке. Как и в случае с большинством дизайнерских решений, существуют нечеткие границы между вариантами выбора (IMO). Стоит отметить, что расширения могут выполняться только для статических классов верхнего уровня, а не для вложенных классов. Если ваше перечисление является частью класса, вам необходимо создать класс.
FREETEXT
51
Вы также можете добавить метод расширения к типу Enum, а не к экземпляру Enum:
/// <summary> Enum Extension Methods </summary>/// <typeparam name="T"> type of Enum </typeparam>publicclassEnum<T>where T :struct,IConvertible{publicstaticintCount{get{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}}
Вы можете вызвать указанный выше метод расширения, выполнив:
var result =Enum<Duration>.Count;
Это не настоящий метод расширения. Это работает только потому, что Enum <> - это другой тип, чем System.Enum.
Может ли класс staticгарантировать, что все его методы ведут себя как расширения?
Джатин Сангхви
15
Для будущих читателей: двусмысленность названия Enum<T>немного сбивает с толку. Класс также может быть вызван, EnumUtils<T>и вызов метода разрешится EnumUtils<Duration>.Count.
Намошек
46
Конечно, вы можете, например, использовать для DescriptionAttribueсвоих enumзначений:
using System.ComponentModel.DataAnnotations;publicenumDuration{[Description("Eight hours")]Day,[Description("Five days")]Week,[Description("Twenty-one days")]Month}
Теперь вы хотите иметь возможность делать что-то вроде:
Duration duration =Duration.Week;var description = duration.GetDescription();// will return "Five days"
Ваш метод расширения GetDescription()можно записать следующим образом:
using System.ComponentModel;
using System.Reflection;publicstaticstringGetDescription(thisEnumvalue){FieldInfo fieldInfo =value.GetType().GetField(value.ToString());if(fieldInfo ==null)returnnull;var attribute =(DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));return attribute.Description;}
Я искал расширение почти точно для того, что делал ваш образец, за исключением того, что я использовал DisplayAttribute Localized GetDescription. ура
Джордж
Это хорошая альтернатива, хотя я думаю, что пространство имен - это просто System.ComponentModel?
TomDestry
Хорошая перспектива и спасибо за то, что показали реализацию, а также код расширения. Вкратце: в своей реализации вы также можете называть ее так: var description = Duration.Week.GetDescription ();
Спенсер Салливан,
32
Все ответы хороши, но они говорят о добавлении метода расширения к определенному типу перечисления.
Что, если вы хотите добавить метод ко всем перечислениям, например, вернуть int текущего значения вместо явного приведения?
publicstaticclassEnumExtensions{publicstaticintToInt<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");return(int)(IConvertible) soure;}//ShawnFeatherly funtion (above answer) but as extention methodpublicstaticintCount<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}
Уловка IConvertibleзаключается в иерархии наследования, см. MDSN
То же самое. Он работает, если я вызываю расширение напрямую (например MyExtention.DoThing(myvalue)), но на самом деле не присоединяюсь к перечислению (например myvalue.DoThing())
Sinaesthetic 05
1
К вашему сведению, C # 7.3 теперь поддерживает Enum как ограничение универсального типа
redtetrahedron
7
Вы можете создать расширение даже для чего угодно object(хотя это не считается лучшей практикой ). Поймите метод расширения как public staticметод. Вы можете использовать любой тип параметра в методах.
voidВозвращаемое значение на перечисление является своего рода странно. Я бы подумал о более реалистичном образце.
psubsee2003
3
@ psubsee2003 у ОП наверняка достаточно знаний, чтобы изменить это в соответствии со своими потребностями? Почему образец имеет значение, этого достаточно, чтобы ответить на первоначальный вопрос.
Люк Хеннерли
3
Я единственный, кто считает примеры кода в MSDN странными? В большинстве случаев вам нужны реальные усилия, чтобы понять, что они пытаются делать!
TimeSpan
Day.IsWorkday()
через(Day & Days.Workday) > 0
сDays.Workday
определяется какMonday | Tuesday ... | Friday
. Первый вариант, на мой взгляд, более понятен, и в нем реализовано именно второе.Ответы:
Согласно этому сайту :
Методы расширения позволяют писать методы для существующих классов таким образом, чтобы другие люди в вашей команде могли их обнаружить и использовать. Учитывая, что перечисления являются такими же классами, как и любые другие, неудивительно, что вы можете их расширить, например:
Я думаю, что перечисления - не лучший выбор в целом, но, по крайней мере, это позволяет вам централизовать часть обработки switch / if и немного их абстрагировать, пока вы не сможете сделать что-то лучше. Не забудьте также проверить, что значения находятся в диапазоне.
Вы можете прочитать больше здесь, на Microsft MSDN.
источник
Duration d = 0;
Given that enums are classes
нет, это не классы.Вы также можете добавить метод расширения к типу Enum, а не к экземпляру Enum:
Вы можете вызвать указанный выше метод расширения, выполнив:
Это не настоящий метод расширения. Это работает только потому, что Enum <> - это другой тип, чем System.Enum.
источник
static
гарантировать, что все его методы ведут себя как расширения?Enum<T>
немного сбивает с толку. Класс также может быть вызван,EnumUtils<T>
и вызов метода разрешитсяEnumUtils<Duration>.Count
.Конечно, вы можете, например, использовать для
DescriptionAttribue
своихenum
значений:Теперь вы хотите иметь возможность делать что-то вроде:
Ваш метод расширения
GetDescription()
можно записать следующим образом:источник
Все ответы хороши, но они говорят о добавлении метода расширения к определенному типу перечисления.
Что, если вы хотите добавить метод ко всем перечислениям, например, вернуть int текущего значения вместо явного приведения?
Уловка
IConvertible
заключается в иерархии наследования, см. MDSNСпасибо ShawnFeatherly за его ответ
источник
MyExtention.DoThing(myvalue)
), но на самом деле не присоединяюсь к перечислению (напримерmyvalue.DoThing()
)Вы можете создать расширение даже для чего угодно
object
(хотя это не считается лучшей практикой ). Поймите метод расширения какpublic static
метод. Вы можете использовать любой тип параметра в методах.источник
См. MSDN .
источник
void
Возвращаемое значение на перечисление является своего рода странно. Я бы подумал о более реалистичном образце.мы только что сделали расширение enum для C # https://github.com/simonmau/enum_ext
Это просто реализация typeafeenum, но она отлично работает, поэтому мы сделали пакет, которым можно поделиться - получайте удовольствие
Я знаю, что этот пример бесполезен, но идею вы поняли;)
источник
Простой обходной путь.
источник