寻找一种更好的方法来排序我的List <T>

cod*_*ife 7 c# .net-3.5 c#-3.0

我正在审查我不久前写的一段代码,我只是讨厌我处理排序的方式 - 我想知道是否有人能够向我展示更好的方法.

我有一个类,Holding其中包含一些信息.我有另一个类,HoldingsList其中包含一个List<Holding>成员.我也有一个枚举,PortfolioSheetMapping它有大约40个左右的元素.

它看起来像这样:

public class Holding
{
    public ProductInfo Product {get;set;} 
    // ... various properties & methods ...
}

public class ProductInfo
{
    // .. various properties, methods... 
}

public class HoldingsList
{
    public List<Holding> Holdings {get;set;}
    // ... more code ...
}

public enum PortfolioSheetMapping
{
    Unmapped = 0,
    Symbol,
    Quantitiy,
    Price,
    // ... more elements ...
}
Run Code Online (Sandbox Code Playgroud)

我有一个方法可以调用List进行排序,具体取决于用户选择的枚举.该方法使用mondo switch语句,有超过40个案例(呃!).

下面的简短代码段说明了代码:

if (frm.SelectedSortColumn.IsBaseColumn)
{
    switch (frm.SelectedSortColumn.BaseColumn)
    {
        case PortfolioSheetMapping.IssueId:
            if (frm.SortAscending)
            {
                // here I'm sorting the Holding instance's
                // Product.IssueId property values...
                // this is the pattern I'm using in the switch...
                pf.Holdings = pf.Holdings.OrderBy
                  (c => c.Product.IssueId).ToList();
            }
            else
            {
                pf.Holdings = pf.Holdings.OrderByDescending
                  (c => c.Product.IssueId).ToList();
            }
            break;
        case PortfolioSheetMapping.MarketId:
            if (frm.SortAscending)
            {
                pf.Holdings = pf.Holdings.OrderBy
                  (c => c.Product.MarketId).ToList();
            }
            else
            {
                pf.Holdings = pf.Holdings.OrderByDescending
                  (c => c.Product.MarketId).ToList();
            }
            break;
        case PortfolioSheetMapping.Symbol:
            if (frm.SortAscending)
            {
                pf.Holdings = pf.Holdings.OrderBy
                  (c => c.Symbol).ToList();
            }
            else
            {
                pf.Holdings = pf.Holdings.OrderByDescending
                  (c => c.Symbol).ToList();
            }
            break;
        // ... more code ....
Run Code Online (Sandbox Code Playgroud)

我的问题在于switch语句.它switchPortfolioSheetMapping枚举紧密相连,可以在明天或第二天改变.每次它改变,我将不得不重新访问这个switch语句,并添加另一个case块.我只是害怕最终这个转换声明会变得如此之大,以至于完全无法管理.

有人能告诉我是否有更好的方法来排序我的清单?

Luk*_*keH 5

你重新分配排序的数据直接回到你的pf.Holdings财产,那么为什么不绕过的开销OrderByToList和仅使用列表的Sort方法,而不是直接?

您可以使用映射来保存Comparison<T>所有支持的排序的委托,然后Sort(Comparison<T>)使用适当的委托进行调用:

if (frm.SelectedSortColumn.IsBaseColumn)
{
    Comparison<Holding> comparison;
    if (!_map.TryGetValue(frm.SelectedSortColumn.BaseColumn, out comparison))
        throw new InvalidOperationException("Can't sort on BaseColumn");

    if (frm.SortAscending)
        pf.Holdings.Sort(comparison);
    else
        pf.Holdings.Sort((x, y) => comparison(y, x));
}

// ...

private static readonly Dictionary<PortfolioSheetMapping, Comparison<Holding>>
    _map = new Dictionary<PortfolioSheetMapping, Comparison<Holding>>
    {
        { PortfolioSheetMapping.IssueId,  GetComp(x => x.Product.IssueId) },
        { PortfolioSheetMapping.MarketId, GetComp(x => x.Product.MarketId) },
        { PortfolioSheetMapping.Symbol,   GetComp(x => x.Symbol) },
        // ...
    };

private static Comparison<Holding> GetComp<T>(Func<Holding, T> selector)
{
    return (x, y) => Comparer<T>.Default.Compare(selector(x), selector(y));
}
Run Code Online (Sandbox Code Playgroud)