0

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; }
}
Ryan Gates
  • 4,501
  • 6
  • 50
  • 90
dance2die
  • 35,807
  • 39
  • 131
  • 194

1 Answers1

4

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Next section in the book deals with "ThenBy"... By the way, does this mean prototype of "OrderBy" (mentioned in the question) is not correct and I would have assume that MSDN document is the most current signature? – dance2die Mar 29 '09 at 22:02
  • Yes, generally go with MSDN - they usually get the signatures right at least. – Jon Skeet Mar 29 '09 at 22:04
  • Call we crazy, but I just use intellisense/object-browser/show-definition - nothing to get wrong then. Although of course MSDN is generated from code anyway (+Sandcastle?) – Marc Gravell Mar 29 '09 at 22:06
  • @Jon: Ouch, when I changed test data around, I was able to see the use of "ThenBy" – dance2die Mar 29 '09 at 22:07