Monday, November 8, 2010

Linq Query operators :part 2

OrderBy Operators

The order operator allows collections to be ordered using orderby, orderbydescending, thenby and thenbydescending. Here is what the prototype looks like:

public static IOrderedEnumerable OrderBy(
this IEnumerable source,
Func keySelector)
where
K : IComparable
 

The operator takes an IEnumerable<T> and orders the collection based on the key selector that will return the key value for each element in the sequence. The only important point that is worth mentioning is that the sorting of orderby and orderbydescending is considered unstable, meaning that if two elements return the same key based on the key selector, the order of the output could be the maintained or could be different. You should never rely on the order of elements coming out of an orderby call other than the field specified in the orderby clause.

Another interesting point that I found was that orderby, orderbydescending and orderbyascending take as an input source IEnumerable, as you can see from the prototype. However, the return type is IORderedEnumerable. The problem with that is if you want to order by more than 1 column, you cannot pass IOrderedEnumerable since orderby takes IEnumerable. The solution to this is to use the ThenBy or ThenByDescending operators, which take IOrderedEnumerble. Let's proceed to an example:

 
public static void OrderByOperators()
    {
        Book[] books =
        {
            new Book{Title="ASP.NET 2.0 Website Programming: Problem -
                Design - Solution",
                Author="Marco Bellinaso"},
            new Book{Title="ASP.NET 2.0 Unleashed", Author="Stephen Walther"},
            new Book{Title="Pro ASP.NET 3.5 in C# 2008,  Second Edition",
                Author="MacDonald and Mario Szpuszta"},
            new Book{Title="ASP.NET 3.5 Unleashed ", Author="Stephen Walther"},
        };
        IEnumerable orderedbooks =
              books.OrderBy(b => b.Author).ThenBy(b => b.Title);
 
    }
 

In the above example, I make use of both orderby and thenby. Since orderby only works on IEnumerable<T>, I make use of the thenby extension method as well. The second prototype for orderby takes in Icomparable and does not require the return type of the keyselector delegate to return a Collection that implements IComparable. Here is what the prototype looks like:

public static IOrderedEnumerable OrderBy(
this IEnumerable source,
Func keySelector,
IComparer comparer);
interface IComparer {
int Compare(T x,  T y);
}

The compare method will return a greater int if the second argument is greater than the first, equal to zero if both arguments are equal and less than zero if the first argument is less than the second. Let's see an example of that:

 
public class LengthComparer : IComparer
{
    public int Compare(string title1,  string title2)
    {
        if (title1.Length < class="code-keyword">return -1;
        else if (title1.Length > title2.Length) return 1;
        else return 0;
    }
}
 

I have created a custom comparer which compares the book title based on the title's length. When the length of the first title is less than the second title's length, I return -1. If it's greater, I return 1. Otherwise, I return 0 for being equal. This is how I make use of the comparer in my LINQ query.

public static void OrderByUsingCustomComparer()
    {
        Book[] books =
        {
            new Book{Title="ASP.NET 2.0 Website Programming: Problem -
                 Design - Solution",
                Author="Marco Bellinaso"},
            new Book{Title="ASP.NET 2.0 Unleashed", Author="Stephen Walther"},
            new Book{Title="Pro ASP.NET 3.5 in C# 2008,  Second Edition",
                Author="MacDonald and Mario Szpuszta"},
            new Book{Title="ASP.NET 3.5 Unleashed ", Author="Stephen Walther"},
        };
        IEnumerable orderedbooks = books.OrderBy(b => b.Title,
            new LengthComparer());
    }

No comments: