Don't you just love Generics? I mean, it helps you alot in so many ways that everytime you are asked about why you love Generics all you could say is "Uh, type safety?".. Err! We need to change that! There are alot more things to like about Generics than just type safety... Like code organization... more readable(if you ask me) code... and of course.. type safety(what? i thought you said there's more) :P
Anyway, I use Generics a lot.. when i say alot I mean really really really a lot(is this sentence correct?). I think I've used it in every code i wrote and its really addicting to use(its like anti-perspirant.. something you cant live without :P). I think i've been crazy about Generics since .NET 2.0 beta that i decided to switch jobs because my employer didnt want to migrate to .NET 2.0(uhmmm, this is joke! Just trying to make a point about it which i think i went over the top). One of the things i really love about Generics is the Sort functionality wherein you can right your own custom Comparer to sort the contents of your Generic list.
Lets start the demonstration by telling a story about a teacher who just got a list of Students and their grades from the last exam.
First, lets look at the structure of the student information. A student has name and grade.
[Student.cs]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class Student { private string _name; private double _grade; public string Name { get { return _name; } set { _name = value; } } public double Grade { get { return _grade; } set { _grade = value; } } public Student(string name, double grade) { this.Name = name; this.Grade = grade; } }}
Each student is a part of big list that contains every student that took the exam
[Students.cs]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class Students: List<Student> { public void Print() { Console.WriteLine("Student\t\tGrade"); Console.WriteLine("-------------------------------"); foreach (Student student in this) { if (student is Student) { Console.WriteLine(student.Name + "\t\t" + student.Grade); } } } }}
The next step is for the teacher to add every student on the list of students that took the exam and print the list.
[Program.cs]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class Program { static void Main(string[] args) { Students students = new Students(); //add the student to the list students.Add(new Student("Tom", 83)); students.Add(new Student("Joe", 86.4)); students.Add(new Student("Rudy", 85)); students.Add(new Student("Chris", 87.2)); students.Add(new Student("Keith", 85.5)); students.Add(new Student("Pepe", 75.1)); students.Add(new Student("Juan", 88.8)); students.Add(new Student("Pedro", 75.1)); students.Add(new Student("Pablo", 75.1)); students.Add(new Student("Jose", 79.3)); students.Add(new Student("Tommy", 88.9)); //print the list students.Print(); Console.ReadLine(); } }}
[Execution Results]
Student Grade---------------------Tom 83Joe 86.4Rudy 85Chris 87.2Keith 85.5Pepe 75.1Juan 88.8Pedro 75.1Pablo 75.1Jose 79.3Tommy 88.9
After printing the list... The teacher realized that the list is not ordered by grade.. He then decided that the report would look better if the grades are ordered in descending order so that he can easily spot the student who didn't do well in the exam instead of browsing each line.
[StudentGradeComparer.cs]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class StudentGradeComparer: IComparer<Student> { #region IComparer<Student> Members public int Compare(Student student1, Student student2) { int returnValue = 1; if (student1 is Student && student2 is Student) { returnValue = student2.Grade.CompareTo(student1.Grade); } return returnValue; } #endregion }}
[revised Program.cs]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class Program { static void Main(string[] args) { Students students = new Students(); //add the student to the list students.Add(new Student("Tom", 83)); students.Add(new Student("Joe", 86.4)); students.Add(new Student("Rudy", 85)); students.Add(new Student("Chris", 87.2)); students.Add(new Student("Keith", 85.5)); students.Add(new Student("Pepe", 75.1)); students.Add(new Student("Juan", 88.8)); students.Add(new Student("Pedro", 75.1)); students.Add(new Student("Pablo", 75.1)); students.Add(new Student("Jose", 79.3)); students.Add(new Student("Tommy", 88.9)); //implement our custom comparer for grades students.Sort(new StudentGradeComparer()); students.Print(); Console.ReadLine(); } }}
[Execution Result]
Student Grade-----------------------Tommy 88.9Juan 88.8Chris 87.2Joe 86.4Keith 85.5Rudy 85Tom 83Jose 79.3Pablo 75.1Pepe 75.1Pedro 75.1
Looking at the result.. He was really happy.. but.. he realized that the names are not alphabetized.. Pedro should come before Pepe because he thinks that names should be in ascending order and rades should be in descending order... being a picky as he is, he decided to add another sort criteria..
[StudentGradeAndNameComparer]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class StudentGradeAndNameComparer : IComparer<Student> { #region IComparer<Student> Members public int Compare(Student student1, Student student2) { int returnValue = 1; if (student1 != null && student2 == null) { returnValue = 0; } else if (student1 == null && student2 != null) { returnValue = 0; } else if (student1 != null && student2 != null) { if (student1.Grade.Equals(student2.Grade)) { returnValue = student1.Name.CompareTo(student2.Name); } else { returnValue = student2.Grade.CompareTo(student1.Grade); } } return returnValue; } #endregion }}
[Modified Program.cs v2]
using System;using System.Collections.Generic;using System.Text;namespace KeithRull.LetsSortThat{ class Program { static void Main(string[] args) { Students students = new Students(); //add the student to the list students.Add(new Student("Tom", 83)); students.Add(new Student("Joe", 86.4)); students.Add(new Student("Rudy", 85)); students.Add(new Student("Chris", 87.2)); students.Add(new Student("Keith", 85.5)); students.Add(new Student("Pepe", 75.1)); students.Add(new Student("Juan", 88.8)); students.Add(new Student("Pedro", 75.1)); students.Add(new Student("Pablo", 75.1)); students.Add(new Student("Jose", 79.3)); students.Add(new Student("Tommy", 88.9)); //implement our custom comparer for grades and names students.Sort(new StudentGradeAndNameComparer()); students.Print(); Console.ReadLine(); } }}
Student Grade---------------------Tommy 88.9Juan 88.8Chris 87.2Joe 86.4Keith 85.5Rudy 85Tom 83Jose 79.3Pablo 75.1Pedro 75.1Pepe 75.1
And finally... He is happy! Sweet.
Hope you learned something about Generics, IComparer, Comparing objects and how crazy teachers can be :)
Download the code here: KeithRull.LetsSortThat.zip (23.85 KB)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.