May 31 2006

Sort List<T> ASC/DESC with Specified Field

Category:Bil@l @ 08:25

In an ASP.NET 2.0 Web application I am working on, there is a need to use a List<LocalDocument>, where the LocalDocument is a class representing a simple document in the mean time.
However, I have decided to add some functionality to the default sorting that comes with the List<T>.

I have added the ability to sort based on any field inside the LocalDocument object.
I also added the ability to sort either Ascending or Descending, where Sort() method always sorts in Ascending order.
I used IComparable<T> and IComparer<T> to accomplish this task. For the IComparer<T> I just provided implementation for the Compare method, that will call the CompareTo method in the LocalDocument object, which is the implementation required by the IComparable<T>.

It's action time :), let us check the code:

LocalDocument.cs
-------------------------------------------
public class LocalDocument : IComparable
{
    #region Private Fields
    private int m_ID;
    private string m_ReferenceID;
    private string m_Title;
    #endregion

    #region Constructors
    public LocalDocument()
    { }

    public LocalDocument(int p_ID, string p_ReferenceID, string p_Title)
    {
        this.m_ID = p_ID;
        this.m_ReferenceID = p_ReferenceID;
        this.m_Title = p_Title;
    }
    #endregion

    #region Public properties
    public int ID
    {
        get { return this.m_ID; }
        set { this.m_ID = value; }
    }
    public string Title
    {
        get { return this.m_Title; }
        set { this.m_Title = value; }
    }
    public string ReferenceID
    {
        get { return this.m_ReferenceID; }
        set { this.m_ReferenceID = value; }
    }
    #endregion

    #region IComprable Methods
    ///
    /// Method to implement from IComparable
    ///
    ///
    ///
    public int CompareTo(LocalDocument p_LocalDocument)
    {
        return m_Title.CompareTo(p_LocalDocument.m_Title);
    }

    public int CompareTo(LocalDocument p_LocalDocument, LocalDocumentComparer.ComparisonType p_ComparisonMethod)
    {
        switch (p_ComparisonMethod)
        {
            case LocalDocumentComparer.ComparisonType.ID:
                return m_ID.CompareTo(p_LocalDocument.m_ID);
            case LocalDocumentComparer.ComparisonType.ReferenceID:
                return m_ReferenceID.CompareTo(p_LocalDocument.m_ReferenceID);
            case LocalDocumentComparer.ComparisonType.Title:
                return m_Title.CompareTo(p_LocalDocument.m_Title);
            default:
                return m_ID.CompareTo(p_LocalDocument.m_ID);
        }
    }
    #endregion
}

We have implemented the CompareTo method in a way to take as input an instance of LocalDocument and the Enumerator to specify the Field to based our comparison on. Notice that we have implemented the IComparable<T> interface.

LocalDocumentComparer.cs
------------------------------------------------------
public class LocalDocumentComparer : IComparer
{
    public enum ComparisonType
    {
        ID = 1,
        ReferenceID = 2,
        Title = 3
    }

    public enum SortOrderType
    {
        ASC = 1,
        DESC = 2
    }

    #region Public & Private fields
    private ComparisonType m_ComparisonType;
    public ComparisonType ComparisonMethod
    {
        get{return this.m_ComparisonType;}
        set{this.m_ComparisonType = value;}
    }
    private SortOrderType m_SortOrderType;
    public SortOrderType SortOrder
    {
        get { return this.m_SortOrderType; }
        set { this.m_SortOrderType = value; }
    }

    #endregion

    #region IComparer Methods
    public int Compare(LocalDocument p_LocalDocument1, LocalDocument p_LocalDocument2)
    {
        if (m_SortOrderType == SortOrderType.ASC)
            return p_LocalDocument1.CompareTo(p_LocalDocument2, m_ComparisonType);

        return p_LocalDocument2.CompareTo(p_LocalDocument1, m_ComparisonType);
    }
    #endregion
}

Notice how we have implemented the IComparer<T>. I have added two Enums, one to set the Comparison Method based on a specific field and one to set the sort order, either ASC or DESC.
The Compare method checks the SortOrder Enum and calls the CompareTo method of the LocalDocument object based on the SortOrder.

How to sort now?
------------------------------------------------------------------------
LocalDocumentComparer _comp = new LocalDocumentComparer();
_comp.SortOrder = LocalDocumentComparer.SortOrderType.DESC;
_comp.ComparisonMethod = LocalDocumentComparer.ComparisonType.ID;
_List.Sort(_comp);

You have specified the SortOrder and Comparison Field, then you call the overloaded method that takes as input a comparer of type IComparer<T>.
I have based my code on my MVP Colleague David Hayden's code in his blog post that can be found here: Implementing IComparer for Sorting Custom Objects . David's way is based on the non-generic IComparable and IComparer. I have also added the SortOrder Enum to David's method.

Hope this helps you!

Regards

 

Tags:

Comments are closed