如何向Enums添加扩展方法

use*_*292 103 .net c# enums

我有这个枚举代码:

enum Duration { Day, Week, Month };
Run Code Online (Sandbox Code Playgroud)

我可以为此枚举添加扩展方法吗?

One*_*rew 95

根据这个网站:

扩展方法提供了一种以团队中其他人可能实际发现和使用的方式为现有类编写方法的方法.鉴于枚举类似于任何其他类,因此您可以扩展它们并不会太令人惊讶,例如:

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");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我认为枚举通常不是最好的选择,但至少这可以让你集中一些开关/如果处理并将它们抽象一点,直到你可以做得更好.请记住检查值是否在范围内.

你可以阅读更多在这里在MSDN的Microsft.

  • "鉴于枚举是类,不是它们不是类. (8认同)
  • @WingerSendon 如果你在 VS2019 中按 F12 键“Enum”(不是“enum”),它会带你到元数据,其中包括“公共抽象类 Enum : ValueType, IComparable, ...” - 所以对我来说它看起来像一个类,因为我认为 enum 和 Enum 是同义词。 (4认同)
  • 仅当直接与枚举相关时,我才使用此类扩展,例如一周中的几天和扩展方法 IsWeekday()、IsWeekendday()。但类的目的是封装行为,因此如果需要封装很多或复杂的行为,类可能会更好。如果它是有限的和基本的,我个人认为枚举的扩展还可以。与大多数设计决策一样,选择之间的界限也很模糊(IMO)。值得注意的是,扩展只能在顶级静态类上完成,而不能在嵌套类上完成。如果你的枚举是一个类的一部分,你需要创建一个类。 (3认同)

Sha*_*rly 40

您还可以向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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过执行以下操作来调用上面的扩展方法:

var result = Enum<Duration>.Count;
Run Code Online (Sandbox Code Playgroud)

这不是一个真正的扩展方法.它只能起作用,因为Enum <>是一个与System.Enum不同的类型.

  • 对于将来的读者:“ Enum &lt;T&gt;”的名称含糊不清有点令人困惑。该类也可以称为“ EnumUtils &lt;T&gt;”,方法调用将解析为“ EnumUtils &lt;Duration&gt; .Count”。 (7认同)
  • 从 C# 7.3 开始,您实际上可以使用 `where T : struct, IConvertible` 而不是 `where T : struct, IConvertible` (我猜,然后还可以删除 ArgumentException) (5认同)

Sta*_*ked 36

当然,例如,您可以使用DescriptionAttribue您的enum值:

using System.ComponentModel.DataAnnotations;

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

    [Description("Five days")]
    Week,

    [Description("Twenty-one days")] 
    Month 
}
Run Code Online (Sandbox Code Playgroud)

现在你希望能够做到这样的事情:

Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"
Run Code Online (Sandbox Code Playgroud)

您的扩展方法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;
}
Run Code Online (Sandbox Code Playgroud)


Bas*_*ANI 26

所有答案都很棒,但他们正在讨论将扩展方法添加到特定类型的枚举

如果你想为所有枚举添加方法,比如返回当前值的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

其背后的技巧IConvertible是它的继承层次结构,请参阅MDSN

感谢ShawnFeatherly的回答

  • 你能用它来表示,这对我不起作用. (7认同)
  • 仅供参考,C# 7.3 现在支持 Enum 作为泛型类型约束 (3认同)
  • 最佳答案! (2认同)

Tim*_*ter 7

您甚至可以为任何事物创建扩展名object(尽管这不是最佳实践).理解扩展方法就像一种public static方法.您可以在方法上使用您喜欢的任何参数类型.

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}
Run Code Online (Sandbox Code Playgroud)


M. *_*put 7

一个简单的解决方法。

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

        return ( int ) ( IConvertible ) payLoad;

    }
}

int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);
Run Code Online (Sandbox Code Playgroud)


Luk*_*ley 5

参见MSDN

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

  • 枚举上的“ void”返回值有点奇怪。我会考虑一个更现实的示例。 (7认同)
  • @ psubsee2003 OP当然有足够的知识来更改此设置以满足他的需求?为什么样本很重要,足以回答最初的问题。 (3认同)
  • 我是唯一在MSDN上发现代码示例很奇怪的人吗?大多数情况下,您需要付出一些真正的努力才能了解他们正在尝试做什么! (3认同)

归档时间:

查看次数:

85177 次

最近记录:

6 年,2 月 前