【问题标题】:shortening simple c# code缩短简单的 C# 代码
【发布时间】:2014-08-06 04:37:46
【问题描述】:

我有这段代码可以完美运行,但对我来说似乎并不漂亮。我想尽可能缩短这段代码。 升序是布尔值,排序是字符串。

if(ascending)
    switch (sort)
    {
        case "ID":
            return lstFiltered.OrderBy(o => o.ID).ToList();
        case "Device_Name":
            return lstFiltered.OrderBy(o => o.Device_Name).ToList();
        case "ErrorType_Name":
            return lstFiltered.OrderBy(o => o.ErrorType_Name).ToList();
        case "Error_Name":
            return lstFiltered.OrderBy(o => o.Error_Name).ToList();
        case "WAIT_TIME":
            return lstFiltered.OrderBy(o => o.WAIT_TIME).ToList();
        default:
            return lstFiltered;
    }
else
    switch (sort)
    {
        case "ID":
            return lstFiltered.OrderByDescending(o => o.ID).ToList();
        case "Device_Name":
            return lstFiltered.OrderByDescending(o => o.Device_Name).ToList();
        case "ErrorType_Name":
            return lstFiltered.OrderByDescending(o => o.ErrorType_Name).ToList();
        case "Error_Name":
            return lstFiltered.OrderByDescending(o => o.Error_Name).ToList();
        case "WAIT_TIME":
            return lstFiltered.OrderByDescending(o => o.WAIT_TIME).ToList();
        default:
            return lstFiltered;
    }

【问题讨论】:

  • 那是lstFiltered的类型?
  • 这本质上是一个代码审查请求。
  • LstFiltered 是对象列表,但对象类型每次都不同。

标签: c# optimization switch-statement


【解决方案1】:

使用Reverse去掉第二个开关:

// define sorted as IEnumerable<T> where T is the actual generic type of lstFiltered

switch (sort)
{
    case "ID":
        sorted = lstFiltered.OrderBy(o => o.ID);
        break;
    case "Device_Name":
        sorted = lstFiltered.OrderBy(o => o.Device_Name);
        break;
    case "ErrorType_Name":
        sorted = lstFiltered.OrderBy(o => o.ErrorType_Name);
        break;
    case "Error_Name":
        sorted = lstFiltered.OrderBy(o => o.Error_Name);
        break;
    case "WAIT_TIME":
        sorted = lstFiltered.OrderBy(o => o.WAIT_TIME);
        break;
    default:
        sorted = lstFiltered;
}

if (!ascending) // do reverse ordering
    sorted = sorted.Reverse();

return sorted.ToList();

【讨论】:

  • Tanx 很多,但是 Reverse() 返回类型是无效的! :)
  • @Mary: List&lt;T&gt;.Reverse() 是无效的,但 IEnumerable&lt;T&gt; 上的 linq 扩展不是!
【解决方案2】:

esskar 的解决方案,在这里稍微反思一下..

var sorted = lstFiltered.OrderBy(
               o => o.GetType()
                     .GetProperty( sort )
                     .GetValue( o, null ));
if (!ascending)
    sorted = sorted.Reverse();
return sorted.ToList();

【讨论】:

【解决方案3】:

【讨论】:

    【解决方案4】:

    实现此目的的一个有趣方法是通过反射。其他答案使用反射来获取属性,然后为每个元素获取一次它的值,这相当慢。

    更好的方法是只获取一次属性,然后为每个元素调用一次它的 getter:

    IEnumerable<T> sorted = lstFiltered;
    var property = typeof(T).GetProperty(sort);
    if (property != null)
        if (ascending)
            sorted = sorted.OrderBy(o => property.GetValue(o, null));
        else
            sorted = sorted.OrderByDescending(o => property.GetValue(o, null));
    return sorted.ToList();
    

    请注意,这会检测到不存在的属性的使用,并且(与原始代码一样)在这种情况下不会对列表进行排序。

    不过,更好(更快)的是使用反射创建一个可以传递给OrderBy的委托:

    IEnumerable<T> sorted = lstFiltered;
    var property = typeof(T).GetProperty(sort);
    if (property != null)
    {
        var getter = (Func<T, object>)Delegate
                        .CreateDelegate(typeof(Func<T, object>),
                                        property.GetGetMethod());
        if (ascending)
            sorted = sorted.OrderBy(getter);
        else
            sorted = sorted.OrderByDescending(getter);
    }
    return sorted.ToList();
    

    不过,这只适用于引用类型。如果您要使用值类型,最简单的方法可能就是为OrderBy 创建一个表达式并编译它。这需要一点时间来编译,但会尽可能快地执行:https://stackoverflow.com/a/7265354/310574

    【讨论】:

    • 我同意,获得一次财产,然后将其传递给lamba
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-29
    • 2022-01-19
    • 2010-11-18
    相关资源
    最近更新 更多