C#通过枚举迭代?

C# Iterating through an enum? (Indexing a System.Array)

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
// Obtain the string names of all the elements within myEnum
String[] names = Enum.GetNames( typeof( myEnum ) );

// Obtain the values of all the elements within myEnum
Array values = Enum.GetValues( typeof( myEnum ) );

// Print the names and values to file
for ( int i = 0; i < names.Length; i++ )
{
    print( names[i], values[i] );
}

但是,我不能索引值。有更简单的方法吗?

或者我完全错过了什么!


1
2
3
4
5
6
Array values = Enum.GetValues(typeof(myEnum));

foreach( MyEnum val in values )
{
   Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
}

或者,可以强制转换返回的System.Array:

1
2
3
4
5
6
7
string[] names = Enum.GetNames(typeof(MyEnum));
MyEnum[] values = (MyEnum[])Enum.GetValues(typeof(MyEnum));

for( int i = 0; i < names.Length; i++ )
{
    print(names[i], values[i]);
}

但是,您能确定getValues返回值的顺序与getNames返回名称的顺序相同吗?


您需要强制转换数组-返回的数组实际上是所请求的类型,即,如果您请求typeof(myEnum),则返回myEnum[]

1
myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));

然后是values[0]


可以将该数组强制转换为不同类型的数组:

1
myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));

或者如果需要整数值:

1
int[] values = (int[])Enum.GetValues(typeof(myEnum));

当然,您可以迭代那些强制转换的数组:)


字典列表怎么样?

1
2
3
4
5
Dictionary<string, int> list = new Dictionary<string, int>();
foreach( var item in Enum.GetNames(typeof(MyEnum)) )
{
    list.Add(item, (int)Enum.Parse(typeof(MyEnum), item));
}

当然,您可以将字典值类型更改为枚举值是什么。


另一个解决方案,具有有趣的可能性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }

static class Helpers
{
public static IEnumerable<Days> AllDays(Days First)
{
  if (First == Days.Monday)
  {
     yield return Days.Monday;
     yield return Days.Tuesday;
     yield return Days.Wednesday;
     yield return Days.Thursday;
     yield return Days.Friday;
     yield return Days.Saturday;
     yield return Days.Sunday;
  }

  if (First == Days.Saturday)
  {
     yield return Days.Saturday;
     yield return Days.Sunday;
     yield return Days.Monday;
     yield return Days.Tuesday;
     yield return Days.Wednesday;
     yield return Days.Thursday;
     yield return Days.Friday;
  }
}


这是另一个。我们需要为我们的枚举值提供友好的名称。我们使用System.ComponentModel.DescriptionAttribute为每个枚举值显示自定义字符串值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static class StaticClass
{
    public static string GetEnumDescription(Enum currentEnum)
    {
        string description = String.Empty;
        DescriptionAttribute da;

        FieldInfo fi = currentEnum.GetType().
                    GetField(currentEnum.ToString());
        da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
                    typeof(DescriptionAttribute));
        if (da != null)
            description = da.Description;
        else
            description = currentEnum.ToString();

        return description;
    }

    public static List<string> GetEnumFormattedNames<TEnum>()
    {
        var enumType = typeof(TEnum);
        if (enumType == typeof(Enum))
            throw new ArgumentException("typeof(TEnum) == System.Enum","TEnum");

        if (!(enumType.IsEnum))
            throw new ArgumentException(String.Format("typeof({0}).IsEnum == false", enumType),"TEnum");

        List<string> formattedNames = new List<string>();
        var list = Enum.GetValues(enumType).OfType<TEnum>().ToList<TEnum>();

        foreach (TEnum item in list)
        {
            formattedNames.Add(GetEnumDescription(item as Enum));
        }

        return formattedNames;
    }
}

在使用中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 public enum TestEnum
 {
        [Description("Something 1")]
        Dr = 0,
        [Description("Something 2")]
        Mr = 1
 }



    static void Main(string[] args)
    {

        var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
    }

这将结束返回"something 1"、"something 2"


旧问题,但使用Linq的.Cast<>()的方法稍微更干净一些

1
2
3
4
5
6
var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();

foreach(var val in values)
{
    Console.WriteLine("Member: {0}",val.ToString());    
}


使用foreach循环怎么样,也许你可以使用它?

1
2
3
4
5
6
  int i = 0;
  foreach (var o in values)
  {
    print(names[i], o);
    i++;
  }

也许是那样?


在enum.getValues结果中,强制转换为int将生成数值。使用ToString()生成友好名称。不需要其他调用Enum.GetName。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public enum MyEnum
{
    FirstWord,
    SecondWord,
    Another = 5
};

// later in some method  

 StringBuilder sb = new StringBuilder();
 foreach (var val in Enum.GetValues(typeof(MyEnum))) {
   int numberValue = (int)val;
   string friendyName = val.ToString();
   sb.Append("Enum number" + numberValue +" has the name" + friendyName +"
"
);
 }
 File.WriteAllText(@"C:\temp\myfile.txt", sb.ToString());

 // Produces the output file contents:
 /*
 Enum number 0 has the name FirstWord
 Enum number 1 has the name SecondWord
 Enum number 5 has the name Another
 */

您可以使用格式字符串来简化这个过程。我在用法消息中使用以下代码段:

1
2
3
4
5
writer.WriteLine("Exit codes are a combination of the following:");
foreach (ExitCodes value in Enum.GetValues(typeof(ExitCodes)))
{
    writer.WriteLine("   {0,4:D}: {0:G}", value);
}

d格式说明符将枚举值格式化为十进制。还有一个x说明符提供十六进制输出。

G说明符将枚举格式化为字符串。如果将flags属性应用于枚举,则也支持组合值。有一个f说明符,它的作用就像标志总是存在一样。

请参见enum.format()。


数组有一个getValue(int32)方法,可以使用该方法在指定的索引处检索值。

数组值


古老的问题,但3dave的回答提供了最简单的方法。我需要一个小助手方法来生成一个SQL脚本来解码数据库中的枚举值以进行调试。效果很好:

1
2
3
4
5
6
    public static string EnumToCheater<T>() {
        var sql ="";
        foreach (var enumValue in Enum.GetValues(typeof(T)))
            sql += $@"when {(int) enumValue} then '{enumValue}'";
        return $@"case ?? {sql}else '??' end,";
    }

我用的是静态方法,所以用法是:

1
var cheater = MyStaticClass.EnumToCheater<MyEnum>()

下面是一个简单的方法来迭代您的自定义枚举对象

1
2
3
4
5
For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))

     Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)

Next