We've been using this method for sorting a generic List<>. Recently, we noticed incorrect results when the target property in T was a nullable type (decimal?). Any ideas how to correct?
public void SortList<T>(List<T> dataSource, string fieldName, SortDirection sortDirection)
{
PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
Comparison<T> compare = delegate(T a, T b)
{
bool asc = sortDirection == SortDirection.Ascending;
object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);
return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
};
dataSource.Sort(compare);
}
Above code from Phil Hustead's article, "Sorting Generic Lists and IEnumerables by Object Property Name" http://www.codeproject.com/Articles/27851/Sorting-Generic-Lists-and-IEnumerables-by-Object-P
For instance, for my Employee objects with nullable decimal property Hours.
The nullable hours 107, null, 8, 152, 64, null sorts to 8, null, 64, null, 107, 152.
The nulls should sort, I think, to the beginning or end of the list.
Change your method to
public static void SortList<T>(List<T> dataSource, string fieldName, SortDirection sortDirection)
{
PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
Comparison<T> compare = delegate(T a, T b)
{
bool asc = sortDirection == SortDirection.Ascending;
object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);
if(valueA == null)
{
if(valueB == null)
{
return 0;
}
else
{
return asc ? -1 : 1;
}
}
if(valueB == null)
{
return asc ? 1 : -1;
}
return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
};
dataSource.Sort(compare);
}
Main issue is that you are checking valueA
for IComparable
only, and if valueA == null
- comparison returns that objects are equal, no matter what is in valueB
. When nullable value is boxed (and this is exactly what is happening here) it is represented by an actual value or null
.