【问题标题】:Is it possible to loop through an enum by type?是否可以按类型循环枚举?
【发布时间】:2015-05-14 12:24:19
【问题描述】:

我正在从枚举中创建几个下拉列表。例如,午餐时间枚举的长度将添加如下下拉列表项:

foreach (LunchBreak type in Enum.GetValues(typeof(LunchBreak)))
{
    items.Add(new SelectListItem()
    {
       Text = SiteUtilities.GetEnumDescription(type),
       Value = ((int)type).ToString()
    });
}

我的枚举格式为:

public enum LunchBreak : int
{
    [Description("20 minutes paid")]
    Paid_20 = 0,

    [Description("20 minutes unpaid")]
    Unpaid_20 = 1
}

有没有办法让 foreach 循环通用,这样我就可以传入typeof(LunchBreak),这样我就不必为所有其他枚举重做代码了?

我尝试将它写在我可以传入 LunchBreak 的地方,但它抱怨我使用枚举作为类型。

我尝试做一个像这里这样的扩展方法,所以我可以调用类似 LunchBreak.GetSelectListItems("Please select a lunch break...") 的东西,并查看了几个类似这样的帖子:Create Generic method constraining T to an Enum 但并没有真正了解发生了什么

扩展尝试:

public static class EnumExtensions
{
    public static List<SelectListItem> GetSelectListItems<T>(string defaultValue) where T : struct, IConvertible
    {
        if (typeof(T).IsEnum)
        {
            List<SelectListItem> items = new List<SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = defaultValue,
                    Value = string.Empty
                }
            };

            foreach (T item in Enum.GetValues(typeof(T)))
            {
                items.Add(new SelectListItem()
                {
                    Text = SiteUtilities.GetEnumDescription(item), // this line fails as item is expected to be of type Enum
                    Value = ((int)item).ToString()  // this line fails as I can't cast item as an int
                });
            }

            return items;
        }

        throw new ArgumentException("T must be an enumerated type"); 
    }
}

【问题讨论】:

    标签: c# enums extension-methods


    【解决方案1】:

    你快到了。您需要将其转换为对象,然后将其转换为 Enum。要投射到int,您可以改用Convert.ToInt32。

    public static class EnumExtensions
    {
        public static List<SelectListItem> GetSelectListItems<T>(string defaultValue) where T : struct, IConvertible
        {
            if (!typeof (T).IsEnum)
                throw new ArgumentException("T must be an enumerated type");
    
            List<SelectListItem> items = new List<SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = "Please select a lunch break...",
                    Value = string.Empty
                }
            };
    
            foreach (T item in Enum.GetValues(typeof(T)))
            {
                items.Add(new SelectListItem()
                {
                    Text = SiteUtilities.GetEnumDescription((Enum)(object)item),
                    Value = Convert.ToInt32(item).ToString()
                });
            }
    
            return items;
        }
    }
    

    注意:您没有使用参数defaultValue,您可能需要去掉它,我相信SelectListItem.Value 必须是int 才能更有意义。

    【讨论】:

      【解决方案2】:

      这是一个简单的扩展,我可以构建任何“枚举循环”:

      扩展

      public static class EnumExtension
          {
              public static IEnumerable<T> GetValues<T>(this T e)
              {
                  return Enum.GetValues(e.GetType()).Cast<T>();
              }
      }
      

      用法

      foreach(var t in new MyEnum().GetValues()){
      
      }
      

      【讨论】:

        【解决方案3】:

        应该这样做(我不知道 GetEnumDescription 原型 - 但它可以简单地期望一个对象并反映它。):

         public static IEnumerable<SelectListItem> GetSelectListItems<T>(string defaultValue)
         {
              if(!typeof(T).IsEnum)
                throw new Exception("Not an enum");
        
              yield return new SelectListItem
              {
                  Text = defaultValue,
                  Value = string.Empty
              };
        
              foreach(var item in Enum.GetValues(typeof(T))
              {
                   yield return new SelectListItem
                   {
                        Text = SiteUtilities.GetEnumDescription((Enum)item),
                        Value = Convert.ChangeType(item, typeof(T).GetEnumUnderlyingType().ToString()) // not all enums are int's
                   }
              }
         }
        

        如果需要,您可以使用包装器 ToList() 它。

        【讨论】:

          【解决方案4】:

          下面的代码有效

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          using System.Text.RegularExpressions;
          
          
          namespace ConsoleApplication28
          {
              class Program
              {
                  public enum LunchBreak : int
                  {
                      Paid_20 = 0,
                      Unpaid_20 = 1,
                  }
                  static void Main(string[] args)
                  {
                      foreach (LunchBreak type in Enum.GetValues(typeof(LunchBreak)))
                      {
                          LunchBreak LunchItem = type;
          
                      }
          
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2019-01-24
            • 2014-08-04
            • 1970-01-01
            • 2012-05-30
            • 2012-06-16
            • 1970-01-01
            相关资源
            最近更新 更多