OrderBy Signature Error in Pro LINQ book?

255 Views Asked by At

According to Pro LINQ: Language Integrated Query in C# 2008, Prototype of OrderBy operator is

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

But the MSDN documentation does not have a generics contraint on TKey that it should be of type IComparable<TKey>

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
)

I am basically sorting Inventory by Unit and then by Size.

    var sortedInventories = inventories
                            .OrderBy(inventory => inventory.Unit)
                            .OrderBy(inventory => inventory.Size);

From the above code snippet, lambda expressions simply return inventory properties to sort by. It does not look like an expression that returns IComparer<T>

But according to logic, it looks like the lambda expression should be of type IComparer<T>.

Which one is the correct declaration of OrderBy?
(Apress.com Errata page has no information on it)

Here is a sample application I created to test OrderBy

public class Program
{
    public static void Main(string[] args)
    {
        var inventories = new[] {
            new Inventory { Unit = 1, Size = 2 },
            new Inventory { Unit = 2, Size = 4 },
            new Inventory { Unit = 3, Size = 6 },
        };
        var sortedInventories = inventories
                                .OrderBy(inventory => inventory.Unit)
                                .OrderBy(inventory => inventory.Size);

        foreach (var inventory in sortedInventories)
            Console.WriteLine("Unit: {0}; Size = {1}", inventory.Unit, inventory.Size);
    }
}

public class Inventory
{
    public int Unit { get; set; }
    public double Size { get; set; }
}
1

There are 1 best solutions below

4
On BEST ANSWER

Change your second "OrderBy" to "ThenBy". You're currently resorting everything, so it's effectively by Size and then Unit, but inefficiently. I'm not sure where you think IComparer<T> should come in, unless you specify it as another argument. Basically it uses Comparer<T>.Default unless you specify a separate comparer.

Anyway, your query should be:

var sortedInventories = inventories
                          .OrderBy(inventory => inventory.Unit)
                          .ThenBy(inventory => inventory.Size);

(With your test data you can't tell the difference, because in each case Size = Unit * 2. Try it with one item which has a small Unit and a large Size though.)

Yes, it looks like the book got the signature slightly wrong - possibly due to it changing shortly before release. If you were basically worried about getting the wrong results though, the above is the explanation.