Question IComparer/Interface question

fernando

New member
Joined
Jan 8, 2014
Messages
4
Programming Experience
1-3
Hi friends,

I've been doing coding using .net for a couple of years and doing websites as well, but I haven't use Interface much, or doesn't find a need to use it in anyway.

In some of my code though, I have used the built-in sorting functionality of .net (like ArrayList.sort()), so now I'm trying to fix my mindset to use interface more, but how?

I know that semantics of interface, like it's a contract of some sort that you need to adhere to, so upon researching and reading some articles about it, there is a mention of IComparer when using sorting.

But how can you use ICompare when all you have to do it INHERIT IComparer then implement your own code logic to sort, there's nothing in IComparer that I have seen that uses SORT method directly, unlike ArrayList where you initialize the variable then call

ArrayListVariable.Sort()

I hope you get what I'm trying to say here, I want to incorporate interfaces in my code, and I'm maintaining hard to understand code in my work as well that uses lots of interface implementation but I don't see why they would use it. I've watched Dan Wahlin's video as well, I know how to define and use interface, but seeing IComparer and IComparable example makes it more confusing!

THank you all.
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
901
Location
Norway
Programming Experience
10+
IComparer only has one member, the Compare method that you implement to compare two objects and return the sort relationship between. Sort method know this (the interface contract) when you pass it a IComparer implementation, and will call this method to determine the sort order of the objects.

Since .Net 2.0 one would rather use the strongly typed List<T> and IComparer<T> though, rather than untyped ArrayList and IComparer.
 

fernando

New member
Joined
Jan 8, 2014
Messages
4
Programming Experience
1-3
Thanks John, but even if I don't implement IComparer or IComparable and just do this instead:

List<string> s = new List<string>();

I can still do this:

s.Sort();

So what's the use of interface then?
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,277
Location
Sydney, Australia
Programming Experience
10+
Thanks John, but even if I don't implement IComparer or IComparable and just do this instead:

List<string> s = new List<string>();

I can still do this:

s.Sort();

So what's the use of interface then?

The String class implements IComparable and IComparable<string> so you are using the interface in that case too. If there was no way to compare Strings then there would be no way to sort them. If you were to create a list of some type that didn't implement IComparable then you would not be able to sort that list simply by calling Sort. That's where IComparer comes in: you can provide your own IComparer that a list can use to sort objects that don't provide their own IComparable implementation.

For instance, let's say that you defined this class:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
If you were to create a List<Person> and call its Sort method, what would you expect to happen? There's no inherent way to compare two Person objects so there's no way to sort them into any meaningful order. In order to be able to sort Person objects you must tell the List how to compare them and you do that by passing it an object that implements the IComparer<Person> interface. It can then use the Compare method of that object to compare two Person objects and, by doing that repeatedly, sort the whole list. If you wanted to sort by Name then you could use this implementation:
public class PersonNameComparer : IComparer, IComparer<Person>
{
    public int Compare(object x, object y)
    {
        return this.Compare((Person) x, (Person) y);
    }

    public int Compare(Person x, Person y)
    {
        // Make use of the IComparable implementation of the String class.
        return x.Name.CompareTo(y.Name);
    }
}
and if you wanted to sort by Age then you could use this:
public class PersonAgeComparer : IComparer, IComparer<Person>
{
    public int Compare(object x, object y)
    {
        return this.Compare((Person) x, (Person) y);
    }

    public int Compare(Person x, Person y)
    {
        // Make use of the IComparable implementation of the Int32 structure.
        return x.Age.CompareTo(y.Age);
    }
}
In the first case, two Person objects are compared by their Name properties so the List would be sorted by Name. In the second case, it would be sorted by Age because the Age properties are compared.
 

fernando

New member
Joined
Jan 8, 2014
Messages
4
Programming Experience
1-3
jmcil,

this code from you:

public int Compare(Person x, Person y) {
// Make use of the IComparable implementation of the Int32 structure.
return x.Age.CompareTo(y.Age);
}

Since Age is a string property which already has CompareTo method, why then would I still use IComparer/IComparable since I could implement this same pasted code/method without actually using the interfaces?

Please bear with me, I'm just thick, being a newbie developer and I want someone to stick to my thick brain the reason why I would use a codeless interface.

Appreciate your code and I get the usage, just still having difficulty convincing myself the benefits of interface.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,277
Location
Sydney, Australia
Programming Experience
10+
Since Age is a string property which already has CompareTo method
Age is type int, not string, but that type also has a CompareTo method.
why then would I still use IComparer/IComparable since I could implement this same pasted code/method without actually using the interfaces?
How could you? You don't have a List<int>; you have a List<Person>. If you want to sort a List<Person> then you have to be able to compare Person objects. How do you compare Person objects to determine precedence? The fact is that there is no way to compare Person objects defined so that cannot be sorted. In order to be able to sort the list you have to tell the list how to compare its items and that's what the IComparer implementation does. It's completely up to you how to implement the Compare method but the Compare method has to be there because that's what the Sort method is going to call. If you want to sort by Name then your IComparer compares the Name properties of the two Person objects. If you want to sort by Age then your IComparer compares the Age properties. If you want to sort by Name and then Age then your IComparer compares the Name properties and then the Age properties. You can sort any way you want simply by implementing different comparisons.

How about you try creating a List<Person> with some Person objects in it and then try sorting it without an IComparer and see what happens.

Here's something else to consider. Let's say that you have a List<string> and you want to sort it based on the length of the string from shortest to longest. How would you do that? If you just call Sort on the list then it will sort them alphabetically. The answer is that you can create an IComparer implementation where the Compare method compares the two strings by length instead of by content. You can then pass an instance of that class to the Sort method and it will sort the strings by length.
 

fernando

New member
Joined
Jan 8, 2014
Messages
4
Programming Experience
1-3
It's completely up to you how to implement the Compare method but the Compare method has to be there because that's what the Sort method is going to call.

okay, just nevermind the Sort(), but my concern of implementing the interfaces, where I have quoted you. Since String class has a CompareTo method already, I didn't have to implement IComparer and IComparable but created my own method (MyCompareTest) like so, and use the string's CompareTo method:

public class Program
{
static void Main(string[] args)
{
Program prog = new Program();
Person p1 = new Person("Peter",61);
Person p2 = new Person("James",72);
 
Console.WriteLine ("Return value is: " + prog.MyCompareTest(p2, p1));
Console.ReadKey();
}
public int MyCompareTest(Person x, Person y)
{
return x.name.CompareTo(y.name);
}
}


So, does underneath the String class lurks the interfaces I have mentioned and is used as well?

What I'm just asking is, I have used a built-in method implementation without using the "contract" of interfaces and implementing them and does my implementation of my method somehow calls the interfaces?

thanks
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,277
Location
Sydney, Australia
Programming Experience
10+
okay, just nevermind the Sort(), but my concern of implementing the interfaces, where I have quoted you. Since String class has a CompareTo method already, I didn't have to implement IComparer and IComparable but created my own method (MyCompareTest) like so, and use the string's CompareTo method:

public class Program
{
static void Main(string[] args)
{
Program prog = new Program();
Person p1 = new Person("Peter",61);
Person p2 = new Person("James",72);
 
Console.WriteLine ("Return value is: " + prog.MyCompareTest(p2, p1));
Console.ReadKey();
}
public int MyCompareTest(Person x, Person y)
{
return x.name.CompareTo(y.name);
}
}


So, does underneath the String class lurks the interfaces I have mentioned and is used as well?

What I'm just asking is, I have used a built-in method implementation without using the "contract" of interfaces and implementing them and does my implementation of my method somehow calls the interfaces?

thanks

Firstly, please don't post code snippets as HTML. As you can see, while it retains the syntax highlighting, it loses the indenting and the indenting is the most important feature for making code easy to read, especially for long snippets. Please do as I've done in post #4 and use [xcode=c#] tags for formatting plain text copied from your IDE.

As for the question, if you're going to manually compare two objects then an interface is not required. In your example, it would be possible to compare two instances of your Person class manually by calling your MyComapreTest method directly. Likewise, if you want to compare two String objects then you can call the CompareTo method of one of them and the fact that that method is a member of the IComparable interface is irrelevant. That same method could have been implemented without the IComparable interface and it would work just the same.

Where IComparable becomes important is where instances of a type need to be compared implicitly and sorting is the most obvious example of that. If you had an array or collection of instances of your Person class, you would not be able to sort that array or collection the way you could if it contained Strings or Integers. That's because array or collection would have no idea how to compare two instances. It wouldn't know anything about your MyCompareTest method so your list wouldn't sort.

In short, you don't have to implement IComparable in order to be able to compare two objects manually but you do if you want them to be able to be compared automatically. If you're going to add a method to your class whose purpose it is to compare two instances then, even if you don't think you need it, there is no reason not to implement IComparable and IComparable<T>.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,277
Location
Sydney, Australia
Programming Experience
10+
Top Bottom