Suppose there is a class Person
class Person { public string Name{get;} public string LastName{get;} public Person(string name, string lastName) { Name = name; LastName = lastName; } }
We will sort the collection of such classes by name and surname. Let's write a comparator
class PersonComparer : IComparer<Person> { public int Compare(Person x, Person y) { var ret =string.CompareOrdinal(x.LastName, y.LastName); if(ret != 0) return ret; return string.CompareOrdinal(x.Name, y.Name); } }
Apparently, at first there is a sorting by a surname. But if the surname matches, then we sort by name.
How to use:
var data = new[] { new Person("Vasya", "Pupkin"), new Person("Petya", "Pupkin"), new Person("Alesha", "Pupkin"), new Person("Vasya", "Borisov"), }; Array.Sort(data, new PersonComparer()); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}");
Conclusion
Borisov Vasya Pupkin Alesha Pupkin Petya Pupkin Vasya
If you need a comparators factory, here's an example.
static class PersonComparer { public static IComparer<Person> Create<T>(Func<Person, T> accessor)where T : IComparable { return new PersonComparerImpl<T>(accessor); } class PersonComparerImpl<T> : IComparer<Person> where T : IComparable { Func<Person, T> _accessor; public PersonComparerImpl(Func<Person, T> accessor) { _accessor = accessor; } public int Compare(Person x, Person y) { return Comparer.Default.Compare(_accessor(x),_accessor(y)); } } }
How to use
var data = new[] { new Person("Vasya", "Pupkin"), new Person("Petya", "Pupkin"), new Person("Alesha", "Pupkin"), new Person("Vasya", "Borisov"), }; Array.Sort(data, PersonComparer.Create(p => p.LastName)); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}"); Console.WriteLine("--------------------------"); Array.Sort(data, PersonComparer.Create(p => p.Name)); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}");
Conclusion
Borisov Vasya Pupkin Vasya Pupkin Petya Pupkin Alesha -------------------------- Pupkin Alesha Pupkin Petya Borisov Vasya Pupkin Vasya
Developing the theme, you can roll the factory to sort by several fields. Example
static class PersonComparer { public static IComparer<Person> Create(params Func<Person, IComparable>[] accessors) { return new PersonComparerImpl(accessors); } class PersonComparerImpl : IComparer<Person> { Func<Person, IComparable>[] _accessors; public PersonComparerImpl(Func<Person, IComparable>[] accessors) { _accessors = accessors; } public int Compare(Person x, Person y) { foreach (var accessor in _accessors) { var ret = Comparer.Default.Compare(accessor(x), accessor(y)); if (ret != 0) return ret; } return 0; } } }
How to use
var data = new[] { new Person("Vasya", "Pupkin"), new Person("Petya", "Pupkin"), new Person("Alesha", "Pupkin"), new Person("Vasya", "Borisov"), }; Array.Sort(data, PersonComparer.Create(p => p.LastName)); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}"); Console.WriteLine("--------------------------"); Array.Sort(data, PersonComparer.Create(p => p.Name)); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}"); Console.WriteLine("--------------------------"); Array.Sort(data, PersonComparer.Create(p => p.LastName, p=>p.Name)); foreach (var p in data) Console.WriteLine($"{p.LastName} {p.Name}");
Conclusion
Borisov Vasya Pupkin Vasya Pupkin Petya Pupkin Alesha -------------------------- Pupkin Alesha Pupkin Petya Borisov Vasya Pupkin Vasya -------------------------- Borisov Vasya Pupkin Alesha Pupkin Petya Pupkin Vasya
CompareTo- tym32167