Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"At least one object must implement IComparable" for an INT? As far as I know, it does

Ok, I have a simple IEnumerable<HtmlString> things and I want to divide it up into four equal groups.

var quarter = things.OrderBy(t => t.Foo).Count() / 4;

should do the trick, but instead I get this funkiness:

Server Error in '/' Application. At least one object must implement IComparable. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: At least one object must implement IComparable.

Line 36: int quarter = things.OrderBy(t => t.Foo).Count() / 4;

Anyone know what the heck is going on here? Why would I need to implement IComparable to get a simple count?

like image 852
Scott Baker Avatar asked Sep 21 '12 21:09

Scott Baker


1 Answers

My guess is that this is to do with lazy evaluation of LINQ's OrderBy. For example, if you have:

var things = unsortedThings.OrderBy(foo => foo.Bar);
var quarter = things.Count() / 4;

then if the foo.Bar properties can't be compared with each other, that will throw exactly that exception.

For example:

using System;
using System.Linq;

class Foo {}

class Program
{
    public static void Main()
    {
        var foos = new[] { new Foo(), new Foo() };
        var ordered = foos.OrderBy(x => x);
        Console.WriteLine(ordered.Count());
    }
}

Output:

Unhandled Exception: System.ArgumentException: At least one object must implement IComparable.
   at System.Collections.Comparer.Compare(Object a, Object b)
   at System.Linq.EnumerableSorter`2.CompareKeys(Int32 index1, Int32 index2)
   at System.Linq.EnumerableSorter`1.QuickSort(Int32[] map, Int32 left, Int32 right)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
   at Program.Main()
like image 176
Jon Skeet Avatar answered Oct 19 '22 23:10

Jon Skeet