Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding code repetition when using LINQ

Ok so I have a number of methods that look like this:- which sorts a list by artist, album, year etc.

        public void SortByAlbum(SortOrder sortOrder)
        {
           if (sortOrder == SortOrder.Ascending)
              _list = _list.OrderBy(x => x.Album).ToList();
           else if (sortOrder == SortOrder.Descending)
              _list = _list.OrderByDescending(x => x.Album).ToList();
        }

and this:

        public void SortByArtist(SortOrder sortOrder)
        {
           if (sortOrder == SortOrder.Ascending)
              _list = _list.OrderBy(x => x.Artist).ToList();
           else if (sortOrder == SortOrder.Descending)
              _list = _list.OrderByDescending(x => x.Artist).ToList();
        }

Now obviously this isn't good code so it needs refactoring into one Sort() method but I just cant figure out how to do it in the simplest possible way. I don't care if it uses IComparer or LINQ.

I want it to look something like this:

    public void Sort(SortOrder sortOrder, SortType sortType)
    {
        //implementation here
    }

    public enum SortType
    {
       Artist,
       Album,
       Year
    }

So whats the cleanest way to do this with no code repetition?

Thanks, Lee

like image 698
Lee Treveil Avatar asked Jan 27 '09 22:01

Lee Treveil


2 Answers

You should be able to mimick the signature of the OrderBy extension method:

Update 1 you have to be explicit in the first generic parameter to your keySelector Func. I'm going to take a guess at your type and call it "Song".

public void Sort<TKey>(SortOrder sortOrder,
                       Func<Song, TKey> keySelector)
{
    if (sortOrder == SortOrder.Descending)
    {
        _list = _list.OrderByDescending(keySelector).ToList(); 
    }
    else
    {
        _list = _list.OrderBy(keySelector).ToList(); 
    }
}

Now you can call "Sort" like this:

Sort(SortOrder.Descending, x => x.Album);

Update 2

Following up on Tom Lokhorst's comment: If you want to predefine some shorthand sort criteria, you could do so by defining a class like this:

public static class SortColumn
{
    public static readonly Func<Song, string> Artist = x => x.Artist;
    public static readonly Func<Song, string> Album = x => x.Album;
}

Now you can simply call:

Sort(SortOrder.Descending, SortColumn.Artist);
like image 138
Matt Hamilton Avatar answered Sep 28 '22 09:09

Matt Hamilton


You might try using a generic comparer.

like image 41
davogones Avatar answered Sep 28 '22 10:09

davogones