Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

C#

How do I implement the IComparer interface?

In the C# Collections Course in the Sorting Lists video the following is stated:

"To tell the sort method how to sort, we can create a class that implements the IComparer interface. It has a single method, and it takes two parameters of the same type...

...The compare method works just like the CompareTo method in the IComparable interface. We can pass an instance of this object to the sort method and it will call the compare method in order to determine the order of the objects in the list. We won't implement the IComparer interface here. Instead, I'm going to leave this as an exercise for you to practice implmenting generic interfaces."

I am attempting to implement the IComparer interface on the Square class below, but when calling the sort method on the list I receive the following error:

"System.InvalidOperationException HResult=0x80131509 Message=Failed to compare two elements in the array. Source=mscorlib StackTrace: at System.Collections.Generic.ArraySortHelper1.Sort(T[] keys, Int32 index, Int32 length, IComparer1 comparer) at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer1 comparer) at System.Collections.Generic.List1.Sort(Int32 index, Int32 count, IComparer1 comparer) at System.Collections.Generic.List1.Sort() at Collections.Program.Main() in C:\Users\a683040\source\repos\Collections\Collections\Program.cs:line 35

Inner Exception 1: ArgumentException: At least one object must implement IComparable."

My code is below:

Square.cs

using System;
using System.Collections.Generic;


namespace Collections
{
    class Square : IComparer<Square>
    {
        public int Length;
        public int Width;
        public int Area;
        public Square(int length, int width)
        {
            Length = length;
            Width = width;
            Area = length * width;
        }


        public int Compare(Square x, Square y)
        {
            if (x.Area.CompareTo(y.Area) != 0)
            {
                return x.Area.CompareTo(y.Area);
            }
            else if(x.Length.CompareTo(y.Length) !=0 )
            {
                return x.Length.CompareTo(y.Length);
            }
            else if (x.Width.CompareTo(y.Width) !=0 )
            {
                return x.Width.CompareTo(y.Width);
            }
            else
            {
                return 0;
            }
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;

namespace Collections
{
    class Program
    {
        static void Main()
        {
            List<Square> squares = new List<Square>
            {
                new Square(1,2),
                new Square(3,4),
                new Square(2,2),
                new Square(3,3),
                new Square(2,3)
            };

            //squares.Sort(); <Incorrect line
            squares.Sort(squares[0]); //<Correct line as provided in comments of "Best Answer" by Steven Parker

            foreach (Square square in squares)
            {
                Console.WriteLine($"This box has a length of {square.Length} and a width of {square.Width}.");
            }

            Console.ReadLine();
        }
    }
}

1 Answer

Steven Parker
Steven Parker
231,269 Points

Judging from the error messages, it sounds like you must also implement IComparable and create a "CompareTo" method.

Right, but in the video he made it sound like we should be calling the sort method on the list by implementing IComparer interface with the corresponding Compare method instead of the IComparable interface and the CompareTo method.

Steven Parker
Steven Parker
231,269 Points

But ".sort()" falls back on IComparable if no comparer argument is provided. So if you don't want to implement it also, provide an instance of "Square" (either a new or existing one) to use as a comparer when you call it:

            squares.Sort(squares[0]);

That did it! Thank you very much!