I Need A Dip

Tuesday, January 31, 2006

Sorting Generics with IComparer<T>

I'm a huge fan of Generics.

I've replaced all of my code generated custom colletion classes with List<T>. But along with my simple implementation of CollectionBase I built in some custom sorting for my objects.

I know the correct way would be to implement IComparer with all my objects and sort that way, but the truth is I very rarely sort anything (only when displaying data t the user). I like just running my CodeSmith template against all 25 of my tables to generate some nice objects that take care of all the C.R.U.D. functions, along with the stored procs to make them work.

Meanwhile, back at the ranch, I need to sort my List<T>'s by a particular property value. Here was my solution:
   1:  public enum GenericComparerSortDirection { Asc, Desc } 
   3:  public class GenericComparer<T> : IComparer<T> 
   4:  {    
   5:      private string propertyName; 
   6:      private GenericComparerSortDirection theDirection; 
   8:      public GenericComparer(string propertyName, GenericComparerSortDirection eSortDirection) 
   9:      { 
  10:          this.propertyName = propertyName; 
  11:          this.theDirection = eSortDirection; 
  12:      } 
  14:      public int Compare(T x, T y) 
  15:      { 
  16:          // gets the value of the x property 
  17:          PropertyInfo property = x.GetType().GetProperty(propertyName); 
  18:          object valueOfX = property.GetValue(x, null); 
  20:          // gets the value of the y property 
  21:          property = y.GetType().GetProperty(propertyName); 
  22:          object valueOfY = property.GetValue(y, null); 
  24:          // now make the comparsion 
  25:          if (this.theDirection == GenericComparerSortDirection.Asc) 
  26:              return ((IComparable)valueOfX).CompareTo(valueOfY); 
  27:          else 
  28:              return ((IComparable)valueOfY).CompareTo(valueOfX); 
  29:      }
  30:  }

Now you can sort a generic list of custom objects like this:
   1:  List<MyClass> lstSorted = getABunchOfObjects(); 
   2:  lstSorted.Sort(new GenericComparer<MyClass>("PropertyName", GenericComparerSortDirection.Asc));

I understand that this isn't the most efficient way of sorting (using reflection) but like I said, I don't use this method often, and it works perfectly for my situation.

NOTE: Notice line 17 and 21 use GetType() rather than typeof(T) in case the properties aren't provided by T itself, but by a class derived from T.
Thanks to a suggestion from Jon Skeet

This implementation was inspired by my problem and the following post: http://www.dotnetjunkies.com/Tutorial/5091F698-EF8B-436B-A345-AFBEF18CE229.dcik


Post a Comment

<< Home