Search code examples
.netvb.netsorting.net-2.0

Multisorting using VB.net 2.0


I'm stuck with VB.net 2.0 and I want to sort a List(Of MyObject). I can easly do it using LINQ but as I'm back in the past with only using Framwork 2.0, I must say I don't realy know how to do this. What is the best approach to do this?

I can have many SortFields as well as none... All this because user can choose fields he wants to sort by.

I search a lot about IComparer but it only do it for one field, not many... If I understand well how it works.

What can I do?


Solution

  • Look into creating a Comparer method that does the comparisons.

    For example, to create a comparer that uses two fields: (this is in C#, since my VB is somewhat rusty):

    class MyCustomComparer: Comparer<MyObject>
    {
        public override int Compare(MyObject obj1, MyObject obj2)
        {
            int rslt = obj1.field1.CompareTo(obj2.field1);
            if (rslt != 0)
            {
                rslt = obj1.field2.CompareTo(obj2.field2);
            }
            return rslt;
        }
    }
    

    You can then create one of those objects and pass it to the List.Sort overload that takes a comparison function.

    Things get a little more complicated when the user can specify the fields and the order to sort. What I've done in the pase is to create a method for each field that can be compared, for example:

    private int CompareField1(MyObject obj1, MyObject obj2)
    {
        return obj1.field1.CompareTo(obj2.field1);
    }
    
    private int CompareField2(MyObject obj1, MyObject obj2)
    {
        return obj1.field2.CompareTo(obj2.field2);
    }
    

    And I create a list of function references in the constructor, one for each field that the user specifies. It looks something like this:

    private List<Func<MyObject, MyObject, int>> compares;
    
    public MyCustomComparer(List<int> fieldsToCompare)
    {
        compares = new List<Func<MyObject, MyObject, int>>();
        for (int i = 0; i < fieldsToCompare.Count; ++i)
        {
            switch (fieldsToCompare[i])
            {
                case 1: compares.Add(CompareField1); break;
                case 2: compares.Add(CompareField2); break;
                // other fields here
            }
        }
    }
    

    Your CompareTo method, then, loops through the compares list:

        public override int Compare(MyObject obj1, MyObject obj2)
        {
            for (int i = 0; i < compares.Count; ++i)
            {
                int rslt = compares[i](obj1, obj2);
                if (rslt != 0) return rslt;
            }
            return 0;
        }
    

    It's not especially pretty, but it's quite effective.