简体   繁体   中英

shortening simple c# code

I have this code which works perfectly but it doesn't seem pretty to me. i want to shorten this code as much as possible. ascending is a boolean & sort is string.

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;
    }

use Reverse to get rid of the second switch:

// 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();

esskar's solution with a little bit of reflection here..

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

Check out ScottGu's old article - Dynamic query Library http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

There are also few existing extensions from here How do I specify the Linq OrderBy argument dynamically?

An interesting way to achieve this is via Reflection. Other answers use Reflection to get the property and then get its value once for each element, which is rather slow.

A better way is to get the property only once, and then just call its getter once for every element:

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();

Note that this detects the use of an nonexistant property and (like the original code) does not sort the list in that case.

Even better (faster), though, is to use Reflection to create a delegate that can be passed to 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();

That only works for reference types, though. If you're going to be using value types, the easiest thing is probably to just create an expression for the OrderBy and compile it. This will take a little bit of time to compile, but will execute as fast as possible: https://stackoverflow.com/a/7265354/310574

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM