# Sorting array with respect to two properties

I'm sorting with respect to Width and Length. However, Width has the significance precedence, so Length is only vital if Width is exactly equal (both are integers). The comparison method I've implemented as shown below. Is this a neat trick with doubling the most significant value's comparer or is there a better way?

  List<Thing> things = thingsDictionary.Select(thing
=> thing.Value).ToList();
things.Sort((first, second)
=> 2 * first.Width.CompareTo(second.Width)
+ first.Length.CompareTo(second.Length));

• Wait, is Width a property or a method? I'm confused by first.Width(second.Width) Nov 18, 2014 at 10:36
• Pleas avoid variable names such as things, thingsDictionary and first. This doesn't give any meaning to the variable. Plus, give the datastructure for the class Thing. This looks like pseudo-code and is not fit for reviewing! Nov 18, 2014 at 10:42
• @Heslacher This is real code. But the computer I'm on has no connection to the Internet so I had to retype it by hand. Forgot to bring over CompareTo(...). My sloppiness. Now it's on-topic again. :) Nov 18, 2014 at 13:05
• I'm voting to reopen based on your assertion that this is production code and your correction of the broken code, but I believe you would get a better review if you included more of the surrounding code for context. Also, be prepared to get bashed pretty hard for having a class named Thing..... Nov 18, 2014 at 13:27

It looks like your implementation relies on Width.CompareTo(second.Width) to return either 1, 0, or -1.

This assumption is wrong. If first.Length is greater than second.Length, CompareTo is allowed to return 9999, or 1, or 500. These could very well screw up your additions.

Sure, the current .NET implementation returns either 1, 0, or -1, but that's an implementation detail. Furthermore, other C# implementations or even future version of .NET may return other values.

A correct implementation would be:

things.Sort((first, second)
=> {
var widthComparison = first.Width.CompareTo(second.Width);
if(widthComparison == 0)
return widthComparison;
else return first.Length.CompareTo(second.Length);
});


But instead of fixing your implementation, I would suggest using LINQ's OrderBy and ThenBy instead. It doesn't seem like you need to sort the list in-place, so there's no need to reinvent the wheel.

List<Thing> things = thingsDictionary.Select(thing => thing.Value)
.OrderBy(x => x.Width)
.ThenBy(x => x.Length)
.ToList();

• The implementation was sloppily typed by me. Sorry. I forgot to type in CompareTo (I'm on two computers and dev environment has no Internet access). Nevertheless, your suggestion is still spot on, so +1. Given that I updated my question with the missing method, we need to update your reply accordingly, to make sense, before accepting it. Who's doing that - you or I? :) Nov 18, 2014 at 13:10
The suggestion by dcastro to use LINQ here is good. But if, for some reason, you wanted to keep using List.Sort(), it means you have write a custom IComparer or Comparison.
things.Sort(KeyComparer<Thing>.OrderBy(thing => thing.Width).ThenBy(thing => thing.Length));