1

I'm self-learning C# but I'm still new to it. I want to figure out how to sort multiple objects in List. Here's a tiny snippet of my code. Here's a clarification, I want to order the list in place (not creating a new one) by either midterm/studentName or Final exam score while displaying all three values in the list.

There are two classes. I'm trying to sort the items by students, then midterm scores and then final exam scores individually. as displayed in the toString method of my StudentGrades class. I've looked at the delegate method but I still don't understand how to implement it from https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.sort?view=netcore-3.1 .

Any advice on a simpler approach would help.

public class StudentGrades
{
    public string studentName;
    public int MidtermGrade;
    public int finalExamGrade;

    public StudentGrades()
    {
      //initialize variables to 0 or ""
    }
       
    //some methods here

   public string toString()
   {
       string result = "student: " + studentName + " midterm grade: " + midterm + ...etc;
       return result;
   }
}


public partial class Grades : Form1
{
    List<StudentGrades> studentList; 
    //StudentGrades is a separate class with no parameters in the constructor
    
    public Grades(List<StudentGrades> student)
    {
        this.studentList = student;
        // some code
    }

    private void button3_click(Object sender, EventArgs e)
    {
       this.studentList.Sort(); //default sorting method for sorting students
    }
     
    private void button4_click(//same arguments)
    {
        //sort midterm grades, but don't know how to do it
    }
}



    

   

2 Answers2

3

you can use a delegate 1st compare to names and if the result means the same is the same then compare to grades... and so on can you cascade the sorting result according to your criteria

students.Sort(
    delegate(StudentGrade s1, StudentGrade s)
    {
        int compareResult = s1.studentName.CompareTo(s2.studentName);
        if (compareResult == 0)
        {
            return s1.MidtermGrade.CompareTo(s2.MidtermGrade);
        }
        return compareResult;
    }
);

and using the LINQ

students.OrderBy(s=> s.studentName)
        .ThenBy(s=> s.MidtermGrade);
ΦXocę 웃 Пepeúpa ツ
  • 43,054
  • 16
  • 58
  • 83
  • 2
    I would say that you don't need `delegate(StudentGrade s1, StudentGrade s)` here and just `(s1,s2) => {...}` will work. At least in latest language version. And the second one will not sort existing list. – Guru Stron Sep 13 '20 at 09:21
1

If the sorting is intended for the view, then I recommend sorting using the ICollectionView of the target collection. This is little faster as it doesn't really move items around to reorder the collection. Instead it leaves the original collection as it is and only sorts its view. This is comparable to sorting a meta collection of indices. ICollectionView is also recommended to use for filtering and traversing the collection.

It's also best practice to use properties in C# in order to expose data instead of fields:

public class StudentGrades
{
    public string StudentName { get; set; }
    public int MidtermGrade { get; set; }
    public int FinalExamGrade { get; set; }

    public StudentGrades()
    {
      //initialize variables to 0 or ""
    }
       
    //some methods here

   public string toString() => $"student: {this.StudentName} midterm grade: {this.MidtermGrade} ...etc";
}

Then sort using ICollectionView:

private void button3_click(Object sender, EventArgs e)
{
   ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.studentList);

   // If you don't want to combine sort criteria
   // then remove all previous ones
   collectionView.SortDescriptions.Clear();
   collectionView.SortDescriptions.Add(new SortDescription(nameof(StudentGrades.StudentName), ListSortDirection.Ascending)); 
}
 
private void button4_click(//same arguments)
{
   ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.studentList);

   // If you don't want to combine sort criteria
   // then remove all previous ones
   collectionView.SortDescriptions.Clear();
   collectionView.SortDescriptions.Add(new SortDescription(nameof(StudentGrades.MidtermGrade), ListSortDirection.Ascending)); 
}
BionicCode
  • 13,277
  • 2
  • 17
  • 33
  • How would someone display the sorted list after using Collections.View? – undefined programmer Sep 13 '20 at 22:27
  • You bind the original collection to a `ListBox`. Now, modifying the collection's view will automatically change the displayed data. In WPF controls don't use the collection directly. They all use the default view of the collection. That's why sorting or filtering the view is reflected by the control. You can also bind the collection's view directly to the control. Would also work. – BionicCode Sep 14 '20 at 09:05