views:

740

answers:

3

Hi,

I have an ArrayList of objects that I need to sort in two different fashions, depending on the situation. I followed this example: http://codebetter.com/blogs/david.hayden/archive/2005/03/06/56584.aspx on how to create a PersonComparer by overloading the IComparer object. I liked this method because it allowed me to build an enumerator of sort criteria that I could set on the fly.

However, when I convert my ArrayList to the generic List<T> type, this method no longer works. When I try to pass my "comparer" object, I get the following error:

"The best overloaded method match for 'System.Collections.Generic.List.Sort has some invalid arguments"

My question is: what do I need to change to make this method work? Or more importantly, is there a better way to create multiple custom sorts using Generic lists?

A: 

I suggest you look at the LINQ extension methods OrderBy and ThenBy.

David M
+1  A: 

List.Sort takes one parameter which is a delegate of the following type:

public delegate int Comparison( T x, T y )

After looking at the blog post you linked, I find it likely that your method takes two objects of any type. You should change your method to take two objects of type T (the type of your List).

Example:

Your method probably is something like

int mymethod (object a, object b) { // something }

if your list is a List

then your method should look like this

int mymethod (CustomClass a, CustomClass b) { // something }

Alternatively, it could look like this

int MyMethod2 <T> (T a, T b) { // something }

Brett Widmeier
This method does not work because in order to overload the IComparer object, you must provide a CompareTo method that accepts two objects.
Nitax
I am suggesting that you write a method that with the signature:int MyMethod2 <T> (T a, T b)Then, just pass it into the List<T>.Sort method. Don't make a class that implements IComparer, this method can live anywhere you want it to.
Brett Widmeier
Alright i'll try that out. I also fixed the example by changing the implimentations of IComparer to IComparer<Object>
Nitax
+2  A: 

List<T>.Sort() takes has an overload that takes an IComparer<T>, List<T>.Sort(IComparer<T>). IComparer<T> is just like IComparer, but it's strongly typed.

To get your code to compile, you need to change your IComparer implementation to also implement IComparer<T>. For example, if you have a List<Person>, then your comparer needs to implement IComparer<Person>. For example:

class Person {
    public string FirstName {get; set;}
    public string LastName {get; set;}
}

// Compares by FirstName then LastName
class PersonComparer : IComparer, IComparer<Person> {
    public int Compare(object x, object y)
    {
        var a = x as Person;
        var b = y as Person;
        return Compare(a, b);
    }

    public int Compare(Person x, Person y)
    {
        var comparisons = new Func<Person, Person, int>[]{
            (a, b) => a.FirstName.CompareTo (y.FirstName),
            (a, b) => a.LastName.CompareTo (y.LastName),
        };
        foreach (var f in comparisons) {
            int c = f (x, y);
            if (c != 0)
                return c;
        }
        return 0;
    }
}
jonp