【问题标题】:Generic enum constraint通用枚举约束
【发布时间】:2015-08-25 11:19:55
【问题描述】:

我继承了一个 web api,它在代码中定义了很多枚举,我想将它们转换为一个名为 EnumView 的视图模型类,以便它们可以按如下方式序列化...

{Id:,名称:enumName}

public class EnumView
{
    public int Id { get; set; }
    public string Name { get; set; }
}

在将 Generic 类限制为枚举类型时,我收到警告

约束不能是特殊类'System.Enum'

这是我要使用的通用转换器...

public class EnumViewConverter<T> where T : Enum
{
    public static List<EnumView> ConvertToView()
    {
        List<EnumView> enumViews = new List<EnumView>();

        T[] enumValues = (T[])Enum.GetValues(typeof(T));

        foreach (var enumValue in enumValues)
        {
            var enumView = new EnumView
            {
                Id = (int)enumValue,
                Name = Enum.GetName(typeof(T), enumValue)
            };

            enumViews.Add(enumView);
        }
        return enumViews;
    }
}

如果没有将 T 限制为枚举,则以下转换不会编译...

Id = (int)enumValue,

由于缺乏通用枚举约束的问题,解决此问题的最佳方法是什么?

【问题讨论】:

  • 好的,你已经定义了一个枚举,但是你将如何使用它呢?通过回答这个问题,我们可以找出转换的目的,然后我们可能会想出一个解决方案
  • @leppie - 我在发帖之前已经阅读了那个问题/答案,但觉得它并没有真正回答我的问题。
  • @Hamed 不太确定你在追求什么 - EnumView 将在 API 中序列化。枚举用于服务器端代码...
  • 实际上(int)enumValue 不编译我猜。因为不能保证enumValue 必须是int。顺便说一句,Enum 也是可序列化的。
  • @AmitKumarGhosh 是的,如果我使用 where T: struct 例如,类型 T 不能保证是枚举。我想创建枚举的所有值的列表并在 API 中返回它,而不仅仅是序列化单个枚举值。

标签: c# generics enums


【解决方案1】:

您可以使用:Id = Convert.ToInt32(enumValue) 而不是强制转换 (int)

如果你想在编译时添加一些“约束”来检查类型,你可以设置“where T: struct”,它至少会阻止设置类类型。

【讨论】:

  • 谢谢,我以为我已经测试过了,但没有成功;无论如何,再试一次,你就成功了。
【解决方案2】:

最后我用了……

public static class EnumViewConverter<T> where T : struct
{
    public static List<EnumView> ConvertToView()
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");

        List<EnumView> enumViews = new List<EnumView>();

        T[] enumValues = (T[])Enum.GetValues(typeof(T));

        foreach (var enumValue in enumValues)
        {
            var enumView = new EnumView
            {
                Id = Convert.ToInt32(enumValue),
                Name = Enum.GetName(typeof(T), enumValue)
            };

            enumViews.Add(enumView);
        }
        return enumViews;
    }
}

被...调用

var views = EnumViewConverter<FooBarEnum>.ConvertToView();

感谢所有的帮助,我可以发誓我之前尝试过这个:(

【讨论】:

    【解决方案3】:

    为了扩展我之前的评论,this answer 中描述的技术使用嵌套类,其泛型参数依赖于其父类来模拟泛型Enum 约束。您可以在这里使用这种方法:

    public abstract class ConverterClassUtils<TClass> 
        where TClass : class
    {
        public class ViewConverter<TInner> where TInner : struct, TClass
        {
            public static List<EnumView> ConvertToView()
            {
                List<EnumView> enumViews = new List<EnumView>();
    
                TInner[] enumValues = (TInner[])Enum.GetValues(typeof(TInner));
    
                foreach (var enumValue in enumValues)
                {
                    var enumView = new EnumView
                    {
                        Id = (int)(object)enumValue,
                        Name = Enum.GetName(typeof(TInner), enumValue)
                    };
    
                    enumViews.Add(enumView);
                }
                return enumViews;
            }
        }
    }
    
    public class EnumConverter : ConverterClassUtils<Enum> { }
    

    然后编译如下:

    var view = EnumConverter.ViewConverter<SomeEnum>.ConvertToView();
    

    虽然没有:

    var view = EnumConverter.ViewConverter<int>.ConvertToView();
    

    【讨论】:

    • 感谢您扩展您的建议,最后我选择了下面的代码,因为它更简单。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多