Enum.GetValues() 上的 OrderBy

问题描述 投票:0回答:4

我正在 MVC 4 中从

DropDownList
填充
enum
,并且我想按从大到小的顺序对枚举值进行排序。然而,似乎没有直接的方法来解决这个问题。目前,我正在使用此代码添加到字典中,键是 ID,值是显示文本:

var priorities = Enum.GetValues(typeof(Models.Priority)).OfType<Models.Priority>().ToList();

for (int i = priorities.Count - 1; i >= 0; i--)
{
    Models.Priority priority = priorities[i];
    prioritiesDictionary.Add((int)priority, "Priority " + ((int)priority).ToString());
}

我不认为将枚举值放入列表并向后循环是最有效的方法。枚举中只有四个值,但是是否有更好的方法对

OrderBy
返回的内容执行
Enum.GetValues
操作?我知道按照我的方式做可能对性能影响很小,但我想知道更大的枚举。

c# linq enums
4个回答
28
投票

听起来你只是想要:

var priorities = ((Models.Priority[]) Enum.GetValues(typeof(Models.Priority)))
                                          .OrderByDescending(x => x);

或者避免使用尽可能多的括号:

var priorities = (Models.Priority[]) Enum.GetValues(typeof(Models.Priority));
var ordered = priorities.OrderByDescending(x => x);

目前尚不清楚您当前的代码如何通过为您提供字典来帮助您 - 但上面的代码肯定会为您提供一系列枚举值,从最高到最低排序。您不需要强制转换为

int
,因为相同类型的枚举值已经可以相互比较。

如果您需要清单,只需在

ToList()
通话后拨打
OrderByDescending
即可。


15
投票

这个怎么样:

Enum.GetValues(typeof(Models.Priority))
    .Cast<Models.Priority>()
    .OrderByDescending(x => (int) x)
    .ToList();

您不应该在这种逻辑风格中使用

OfType<T>()
,因为这会默默地丢弃不匹配的项目。在这种情况下,不匹配的项目将表明存在严重错误或误用。

如果期望所有项目都已经是某种类型,那么我们使用

Cast<T>()

OfType<T>
是一个filter操作,它旨在用于我们知道某些项目不能转换为预期类型的场景。因此,
OfType<T>
在可能包含
null
有价值的项目的列表中非常有用。

OfType<T>
通常用于对无类型或
object
枚举(如 Type Attribute)进行操作的表达式中,或者当枚举是基本类型并且您只需要特定实现或实现特定接口的对象时。


4
投票

基于上述,我创建了一个可重用的函数...

    public static IOrderedEnumerable<TEnum> Sort<TEnum>()
    {
        return ((TEnum[]) Enum.GetValues(typeof (TEnum))).OrderBy(x => x.ToString());
    }

2
投票

我喜欢声明一个枚举助手来缓存结果。可以像这样使用:

Enum<MyEnum>.ValuesAscending

这里是帮手

using System;
using System.Collections.Generic;
using System.Linq;
...
  public static class Enum<T>
    where T : struct, Enum
  {
    public static readonly IReadOnlyList<T> ValuesAscending = Enum.GetValues( typeof( T ) ).Cast<T>().Distinct().OrderBy( v => v ).ToArray();
    public static readonly IReadOnlyList<T> ValuesDescending = Enum.GetValues( typeof( T ) ).Cast<T>().Distinct().OrderByDescending( v => v ).ToArray();
    public static readonly IReadOnlyList<string> NamesAscending = Enum.GetNames( typeof( T ) ).OrderBy( s => s ).ToArray();
    public static readonly IReadOnlyList<string> NamesDescending = Enum.GetNames( typeof( T ) ).OrderByDescending( s => s ).ToArray();
  };

注意:

ValuesAscending
ValuesDescending
都消除了重复项,并且仍然适用于除
int
以外的枚举类型。这些列表是使用静态类的静态成员的魔法来缓存的,尽管我不能保证线程安全(如果您需要的话)。如果使用全部四个,您还可以在降序上使用
.Reverse().ToArray()
以节省一些时间。

如果您想要更多帮助程序,我这里有一个更广泛的版本,对您不使用的内容进行延迟缓存:https://github.com/cgbeutler/CSharpEnumExt

© www.soinside.com 2019 - 2024. All rights reserved.