У меня есть этот код Enum:
enum Duration { Day, Week, Month };
Можно ли добавить методы расширения для этого Enum?
У меня есть этот код Enum:
enum Duration { Day, Week, Month };
Можно ли добавить методы расширения для этого Enum?
По данным этого сайта:
Методы расширения предоставляют способ написания методов для существующих классов таким образом, чтобы другие люди в вашей команде могли их обнаружить и использовать. Учитывая, что перечисления являются классами, как и любые другие, не должно быть слишком удивительным, что вы можете расширить их, например:
enum Duration { Day, Week, Month };
static class DurationExtensions
{
public static DateTime From(this Duration duration, DateTime dateTime)
{
switch (duration)
{
case Day: return dateTime.AddDays(1);
case Week: return dateTime.AddDays(7);
case Month: return dateTime.AddMonths(1);
default: throw new ArgumentOutOfRangeException("duration");
}
}
}
Я думаю, что перечисления не лучший выбор в целом, но, по крайней мере, это позволяет вам централизовать некоторые операции переключения/обработки и немного абстрагировать их, пока вы не сможете сделать что-то лучше. Не забудьте проверить значения в диапазоне тоже.
Вы можете прочитать больше здесь на Microsft MSDN.
Вы также можете добавить метод расширения к типу Enum, а не экземпляр Enum:
/// <summary> Enum Extension Methods </summary>
/// <typeparam name="T"> type of Enum </typeparam>
public class Enum<T> where T : struct, IConvertible
{
public static int Count
{
get
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return Enum.GetNames(typeof(T)).Length;
}
}
}
Вы можете вызвать метод расширения выше, выполнив:
var result = Enum<Duration>.Count;
Это не истинный метод расширения. Он работает только потому, что Enum < > является другим типом, чем System.Enum.
Конечно, вы можете, например, сказать, что вы хотите использовать DescriptionAttribue
для своих значений enum
:
using System.ComponentModel.DataAnnotations;
public enum Duration
{
[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;
public static string GetDescription(this Enum value)
{
FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
if (fieldInfo == null) return null;
var attribute = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
return attribute.Description;
}
Все ответы хороши, но они говорят о добавлении метода расширения к определенному типу enum.
Что если вы хотите добавить метод ко всем перечислениям, например, возвращая int текущего значения вместо явного приведения?
public static class EnumExtensions
{
public static int ToInt<T>(this T soure) where T : IConvertible//enum
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return (int) (IConvertible) soure;
}
//ShawnFeatherly funtion (above answer) but as extention method
public static int Count<T>(this T soure) where T : IConvertible//enum
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return Enum.GetNames(typeof(T)).Length;
}
}
Хитрость в IConvertible
заключается в его иерархии наследования, см. MDSN
Спасибо ShawnFeatherly за его ответ
Вы можете создать расширение для чего угодно, даже object
(хотя не считается лучшей практикой). Понимать метод расширения как метод public static
. Вы можете использовать любой тип параметра, который вам нравится в методах.
public static class DurationExtensions
{
public static int CalculateDistanceBetween(this Duration first, Duration last)
{
//Do something here
}
}
Смотрите MSDN.
public static class Extensions
{
public static string SomeMethod(this Duration enumValue)
{
//Do something here
return enumValue.ToString("D");
}
}
мы только что сделали расширение enum для c # https://github.com/simonmau/enum_ext
Это всего лишь реализация для typesafeenum, но она прекрасно работает, поэтому мы создали пакет для совместного использования - развлекайтесь с ним
public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
public static readonly Weekday Monday = new Weekday(1, "--Monday--");
public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
....
private Weekday(int id, string name) : base(id, name)
{
}
public string AppendName(string input)
{
return $"{Name} {input}";
}
}
Я знаю, что этот пример бесполезен, но вы поняли;)