简体   繁体   English

如何向枚举添加扩展方法

[英]How to add extension methods to Enums

I have this Enum code:我有这个枚举代码:

enum Duration { Day, Week, Month };

Can I add a extension methods for this Enum?我可以为此 Enum 添加扩展方法吗?

According to this site :根据这个网站

Extension methods provide a way to write methods for existing classes in a way other people on your team might actually discover and use.扩展方法提供了一种以团队中其他人可能会实际发现和使用的方式为现有类编写方法的方法。 Given that enums are classes like any other it shouldn't be too surprising that you can extend them, like:鉴于枚举是与其他任何类一样的类,因此您可以扩展它们也就不足为奇了,例如:

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");
    }
  }
}

I think enums are not the best choice in general but at least this lets you centralize some of the switch/if handling and abstract them away a bit until you can do something better.我认为枚举通常不是最好的选择,但至少这可以让你集中一些 switch/if 处理并将它们抽象一点,直到你可以做更好的事情。 Remember to check the values are in range too.请记住检查值是否也在范围内。

You can read more here at Microsft MSDN.你可以阅读更多在这里在MSDN的Microsft。

You can also add an extension method to the Enum type rather than an instance of the Enum:您还可以向 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;
        }
    }
}

You can invoke the extension method above by doing:您可以通过执行以下操作来调用上面的扩展方法:

var result = Enum<Duration>.Count;

It's not a true extension method.这不是真正的扩展方法。 It only works because Enum<> is a different type than System.Enum.它之所以有效,是因为 Enum<> 是与 System.Enum 不同的类型。

Of course you can, say for example, you want to use the DescriptionAttribue on your enum values:当然,例如,您可以在enum值上使用DescriptionAttribue

using System.ComponentModel;

public enum Duration 
{ 
    [Description("Eight hours")]
    Day,

    [Description("Five days")]
    Week,

    [Description("Twenty-one days")] 
    Month 
}

Now you want to be able to do something like:现在您希望能够执行以下操作:

Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"

Your extension method GetDescription() can be written as follows:您的扩展方法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;
}

All answers are great, but they are talking about adding extension method to a specific type of enum.所有的答案都很棒,但他们谈论的是向特定类型的枚举添加扩展方法。

What if you want to add a method to all enums like returning an int of current value instead of explicit casting?如果您想向所有枚举添加一个方法,例如返回当前值的 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;
    }
}

The trick behind IConvertible is its Inheritance Hierarchy see MDSN IConvertible背后的技巧是它的继承层次结构,请参阅MDSN

Thanks to ShawnFeatherly for his answer感谢ShawnFeatherly 的回答

You can create an extension for anything, even object (although that's not considered best-practice ).您可以为任何东西创建扩展,甚至是object (尽管这不被认为是最佳实践)。 Understand an extension method just as a public static method.将扩展方法理解为public static方法。 You can use whatever parameter-type you like on methods.您可以在方法上使用任何您喜欢的参数类型。

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}

A Simple workaround.一个简单的解决方法。

public static class EnumExtensions
{
    public static int ToInt(this Enum payLoad) {

        return ( int ) ( IConvertible ) payLoad;

    }
}

int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);

See MSDN .请参阅MSDN

public static class Extensions
{
  public static string SomeMethod(this Duration enumValue)
  {
    //Do something here
    return enumValue.ToString("D"); 
  }
}

we have just made an enum extension for c# https://github.com/simonmau/enum_ext我们刚刚为 c# https://github.com/simonmau/enum_ext做了一个 enum 扩展

It's just a implementation for the typesafeenum, but it works great so we made a package to share - have fun with it它只是 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}";
    }
}

I know the example is kind of useless, but you get the idea ;)我知道这个例子没什么用,但你明白了;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM