IComparer / IComparable are interfaces used to compare two objects. The implementing class has to define the logic for sorting. It provides a way to customize the sort order of a collection.
Implementation of IComparable in WPF. Here, we implement the CompareTo method and sort the Emp objects based on Age property.
Just create a sample WPF application and paste the code as seen below :
Emp class implements IComparable which defines the sort logic.
namespace WpfApplication1
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List empList = new List();
empList.AddRange(new List(){new Emp { Name = "A", Age = 25, Address = "Test StreetA" },
new Emp { Name = "A", Age = 26, Address = "Test StreetA1" },
new Emp { Name = "B", Age = 25, Address = "Test StreetB" },
new Emp { Name = "C", Age = 26, Address = "Test StreetC" },
new Emp { Name = "Z", Age = 25, Address = "Test StreetZ" },
new Emp { Name = "D", Age = 26, Address = "Test StreetD" }});
empList.Sort();
}
}
public class Emp
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
public class Emp : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
#region IComparable Members
public int CompareTo(Emp other)
{
// Sort based on Age
if (this.Age > other.Age)
{
return 1;
}
else if (other.Age > this.Age)
return -1;
else
return 0;
}
#endregion
}
}
Note:
List test = new List();
test.Add("B");
test.Add("C");
test.Add("A");
test.Sort();
This will work because by default List and Array implement IComparable.
But the example below won't work.
public class Emp
{
public string Name { get; set; }
}
// Sorting using IComparable based Age ascending order
List empList = new List();
empList.AddRange(new List(){new Emp { Name = "C25"},
new Emp { Name = "B35"},
new Emp { Name = "A15"}});
empList.Sort();
C# compiler is not smart enough to figure out which instance of type "Emp" should come first etc.
IComparer interface:
But sometimes, we may need to sort a list of objects when the class does not implement IComparable<> interface and also we may need various kinds of sorting on that class like:
- Sort Emp by Age in Ascending Order
- Sort Emp by Age in Descending Order
- Sort Emp by Name
To solve this problem, .NET provides a special interface called IComparer<> which has a method Compare(), takes two object parameters X, Y and returns an int. Use of IComparer<> interface tells List how exactly you want to sort.
namespace WpfApplication1
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Sorting using IComparable based Age ascending order
List empList = new List();
empList.AddRange(new List(){new Emp { Name = "A25", Age = 25, Address = "Test StreetA25" },
new Emp { Name = "B35", Age = 35, Address = "Test StreetB35" },
new Emp { Name = "C15", Age = 15, Address = "Test StreetC15" },
new Emp { Name = "D45", Age = 45, Address = "Test StreetD45" },
new Emp { Name = "E5", Age = 5, Address = "Test StreetE5" }});
// Default sort as defined by IComparable
empList.Sort();
foreach (dynamic emp in empList)
{
string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
myListBox.Items.Add(listTemp);
}
// Create IComparer instance
Emp_SortByAgeByDescendingOrder descSort = new Emp_SortByAgeByDescendingOrder();
// Specify the type
empList.Sort(descSort);
foreach (dynamic emp in empList)
{
string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
myListBox1.Items.Add(listTemp);
}
}
}
public class Emp : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public int CompareTo(Emp other)
{
// Sort based on Age
if (this.Age > other.Age)
{
return 1;
}
else if (other.Age > this.Age)
return -1;
else
return 0;
}
}
class Emp_SortByAgeByDescendingOrder : IComparer
{
#region IComparer Members
public int Compare(Emp x, Emp y)
{ if (x.Age < y.Age) return 1;
else if (x.Age > y.Age) return -1;
else return 0;
}
#endregion
}
class Emp_SortByName : IComparer
{
#region IComparer Members
public int Compare(Emp x, Emp y)
{
return string.Compare(x.Name, y.Name);
}
#endregion
}
}
Special case : If we have both IComparer and IComparable implemented Sort will take place based on IComparer logic first and then followed
by IComparable logic.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List empList = new List();
empList.AddRange(new List(){new Emp { Name = "A", Age = 25, Address = "Test StreetA25" },
new Emp { Name = "A", Age = 35, Address = "Test StreetB35" },
new Emp { Name = "B", Age = 15, Address = "Test StreetC15" },
new Emp { Name = "B", Age = 45, Address = "Test StreetD45" },
new Emp { Name = "C", Age = 5, Address = "Test StreetE5" }});
// Create IComparer instance
// IComparer sorts by Name asc
// IComparable sorts by Age desc
// Sort should be Name asc and Age desc
Emp_SortByName descSort = new Emp_SortByName();
// Specify the type
empList.Sort(descSort);
foreach (dynamic emp in empList)
{
string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
myListBox1.Items.Add(listTemp);
}
}
}
public class Emp : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public int CompareTo(Emp other)
{
// Sort based on Age
if (this.Age > other.Age)
{
return 1;
}
else if (other.Age > this.Age)
return -1;
else
return 0;
}
}
class Emp_SortByName : IComparer
{
#region IComparer Members
public int Compare(Emp x, Emp y)
{
return string.Compare(x.Name, y.Name);
}
#endregion
}
Happy Reading...