Click here to Skip to main content
15,795,712 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Suppose I have a list of student objects where a single student has the properties Name, Age and Company properties. I would like to implement extra Comparer interfaces that will allow me to sort a list of students using the Age and company properties. I have already implemented a default comparer that is based on the Name of the student. The names are compared lexicographically and the sort is executed on the students list. Now I would like to implement additional sort interfaces that let me sort the students list based on the age or the company names lexicographically.
How do I do that in C#?

What I have tried:

public interface IPerson
    string Name { get; set; }
    int Age { get; set; }
    string Company { get; set; }
//implementation details for my Student class
public class Student : IPerson, IComparable<Student>  
    private string _name;
    private string _company;
    private int _age;   
    public string Name { 
        get => _name;
        set => _name = value; }
    public string Company { get => _company; set => _company= value; 
    public int Age { get => _age; set => _age = value; }
    //define the constructor
    public Student(string name, int age, string company)
        _name = name;
        _company = company; 
        _age = age; 
    //the default comparer is name based
    public int CompareTo(Student other)
        return _name.CompareTo(other. Name);    
   //how do I implement additional interfaces for age and company and how do 
   //tell the compiler in Main method to use which type to do it
Updated 15-Jun-23 4:07am

1 solution

Rather than having the class implement the comparison, use external classes implementing IComparer<IPerson>.
public abstract class PersonComparer : IComparer<IPerson>
    public int Compare(IPerson left, IPerson right)
        if (left is null) return right is null ? 0 : -1;
        if (right is null) return 1;
        return CompareCore(left, right);
    protected abstract int CompareCore(IPerson left, IPerson right);

public class PersonNameComparer : PersonComparer
    protected override int CompareCore(IPerson left, IPerson right) => StringComparer.CurrentCulture.Compare(left.Name, right.Name);

public class PersonAgeComparer : PersonComparer
    protected override int CompareCore(IPerson left, IPerson right) => left.Age.CompareTo(right.Age);

public class PersonCompanyComparer : PersonComparer
    protected override int CompareCore(IPerson left, IPerson right) => StringComparer.CurrentCulture.Compare(left.Company, right.Company);
IComparer<T> Interface (System.Collections.Generic) | Microsoft Learn[^]
Share this answer
Tim the Gamer 15-Jun-23 8:54am    
This will make the code complex and a pain to the eye, where is the constructor of this external class and how do I use it to sort a list of Student objects?
Richard Deeming 15-Jun-23 9:03am    
"where is the constructor"
Since there are no constructors defined, the compiler will generate a default constructor.

"how do I use it"
Pass an instance of the class to the List<T>.Sort(IComarer<T>) method[^].
Richard Deeming 15-Jun-23 9:05am    
The other alternative, assuming you only care about List<T> sorting, would be to use a Comparison<T> delegate:
listOfStudents.Sort((x, y) => x is null ? (y is null ? 0 : -1) : (y is null ? 1 : x.Age.CompareTo(y.Age)));

If your list will never contain null values, you can simplify that to:
listOfStudents.Sort((x, y) => x.Age.CompareTo(y.Age));

List<T>.Sort Method (System.Collections.Generic) | Microsoft Learn[^]
Richard Deeming 15-Jun-23 9:07am    
Or, if you're not worried about memory usage, use LINQ:
listOfStudents = listOfStudents.OrderBy(x => x.Age).ToList();
Tim the Gamer 15-Jun-23 9:15am    
_listOfStudents.Sort((x, y) => x.Age.CompareTo(y.Age));_ worked without implementing your class.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900