我可以将 Enum 扩展为 Enum.GetValues() 吗? [复制]

Posted

技术标签:

【中文标题】我可以将 Enum 扩展为 Enum.GetValues() 吗? [复制]【英文标题】:Can I extend Enum a la Enum.GetValues()? [duplicate] 【发布时间】:2014-03-18 04:43:54 【问题描述】:

我想创建一个将任何枚举转换为 Json 字符串的扩展方法。

我希望能够将扩展方法附加到 Enum 中,我可以将枚举类型传递到其中,以便可以在 Enum 上调用它,就像你可以调用 Enum.GetValues(Type enumType) 一样,所以它可能看起来像:

Enum.ToJsonString(Type enumType)

这似乎是不可能的——Enum是一个抽象类;你怎么能延长它? -- 而且我必须创建自己的静态类型来实现它。

谁能确认我不能以这种方式扩展 Enum(请从技术上解释为什么),或者告诉我该怎么做?

澄清(更新)

我知道我可以用我自己的静态类型来做到这一点。例如,创建EnumExtensions.ToJsonString(Type enumType) 相当容易,但我宁愿将方法与 GetValues() 等一起列出,并使用 VS 智能自动完成。

【问题讨论】:

你是指任何枚举,还是任何枚举?扩展方法总是看起来好像它们是 instance 方法,而不是静态方法。了解更多关于您希望您的方法做什么以及如何调用它会很有用。 我的意思是任何枚举。我希望能够将任何枚举的所有可能值转换为 json 字符串,其中名称/哈希码作为 json 中的键/值对象。 【参考方案1】:

正如extension methods在C#中定义的那样:

扩展方法使您能够将方法“添加”到现有类型 无需创建新的派生类型、重新编译或以其他方式 修改原始类型。扩展方法是一种特殊的 静态方法,但它们被调用就好像它们是 instance 方法 扩展类型。

它们应该被调用,因为它们是类型的实例方法。 Enum 是一个类型名称,您正在尝试编写看起来像类型的静态成员的扩展,这是不可能

你可以做的是泛型方法,它将接受枚举类型并将枚举值转换为 JSON:

public static string GetEnumJson<T>()
    where T : struct

    Type type = typeof(T);
    if (!type.IsEnum)
        throw new NotSupportedException();

    var members = Enum.GetNames(type)
                      .ToDictionary(s => s, s => Enum.Parse(type, s));

    return JsonConvert.SerializeObject(members);

并与

一起使用
var json = GetEnumJson<DayOfWeek>();

或者,如果您在 JsonHelper 类中有此方法,那么我将使用名称 GetEnumMembers 和 这样称呼它:

var json = JsonHelper.GetEnumMembers<DayOfWeek>();

结果:

"星期日":0,"星期一":1,"星期二":2,"星期三":3,"星期四":4,"星期五":5,"星期六":6

【讨论】:

@James 基本上没有任何改变 - 答案仍然是 '不可能' :) 看来这可能是最终的答案(我会给出一段时间)。我喜欢另一种通用方法,但我很沮丧我不能指定where T: Enum,如果参数不是枚举,我必须抛出异常......这让人感觉很笨拙。 不错的代码@SergeyBerezovskiy! :) @Faust 同意你的观点——泛型类型参数约束在 C# 中不是很灵活——你不能添加枚举约束。但我至少会为值类型添加约束。另请参阅 ken2k 提到的问题 @Jodrell 你是神话终结者 :)【参考方案2】:

这个怎么样,你不能把它作为一个扩展来做,因为你不能在 c# 中做静态扩展(在撰写本文时)。

请注意,如果两个枚举成员具有相同的值(这是不寻常但有效的),则此代码有效。

public static string ToJson<TEnum>()

    var enumType = typeof(TEnum);
    if (!enumType.IsEnum)
    
        throw new ArgumentException("enumType");
    

    var names = Enum.GetNames(enumType);
    var values = Enum.GetValues(enumType).OfType<Enum>()
        .Select(e => Convert.ChangeType(e, e.GetTypeCode()));
    var members = names.Zip(values, (k, v) => new  k, v )
        .ToDictionary(p => p.k, p => p.v);

    return JsonConvert.SerializeObject(members);

【讨论】:

【参考方案3】:

您可以为所有类型添加扩展,并在内部检查它是否像这样枚举

static class EnumEx

    public static string ToJsonString(this Type enumType)
    
        if(!enumType.IsEnum)
            throw new ArgumentException("Type should be enum");

        return /* create json string from enum type */
    

并像使用它

enum MyEnum

    MyValue1,
    MyValue2,


....

var json = typeof(MyEnum).ToJsonString();

【讨论】:

以上是关于我可以将 Enum 扩展为 Enum.GetValues() 吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

将内容扩展为空div

将 vue-material 组件扩展为我自己的组件

Groovy 将元组/映射扩展为参数

将 ES6 插件扩展为 jQuery 原型

Flutter 如何将小部件扩展为具有更多内容的更大小部件?

将文本片段扩展为更长的文本块