/* C# Programming Tips & Techniques by Charles Wright, Kris Jamsa Publisher: Osborne/McGraw-Hill (December 28, 2001) ISBN: 0072193794 */ // SortEmpl.cs -- Demonstrates using a delegate with a container class to // sort the collection and return a sorted array using different // sort criteria. // // Compile this program with the following command line: // C:>csc SortEmpl.cs using System; using System.ComponentModel; namespace nsDelegates { public class SortEmpl { // Declare an enum for the sort methods. enum SortBy {Name, ID, ZIP}; // Create a container to get the clsEmployee object collection static public clsEmployeeContainer container = new clsEmployeeContainer (); static public void Main () { container.Add (new clsEmployee ("John", "Smith", "87678", 1234)); container.Add (new clsEmployee ("Marty", "Thrush", "80123", 1212)); container.Add (new clsEmployee ("Milton", "Aberdeen", "87644", 1243)); container.Add (new clsEmployee ("Marion", "Douglas", "34567", 3454)); container.Add (new clsEmployee ("Johnathon", "Winters", "53422", 3458)); container.Add (new clsEmployee ("William", "Marmouth", "12964", 3658)); container.Add (new clsEmployee ("Miles", "O'Brien", "63445", 6332)); container.Add (new clsEmployee ("Benjamin", "Sisko", "57553", 9876)); // Show the unsorted employee list. Console.WriteLine ("Unsorted employee list:"); ComponentCollection collectionList = container.GetEmployees(); foreach (clsEmployee emp in collectionList) { Console.WriteLine (" " + emp); } // Sort the employees by last name and show the list. Console.WriteLine (" Sorted by last name:"); clsEmployee [] arr = SortList (SortBy.Name); foreach (clsEmployee emp in arr) { Console.WriteLine (" " + emp); } // Sort the employees by ID number and show the list. Console.WriteLine (" Sorted by employee ID:"); arr = SortList (SortBy.ID); foreach (clsEmployee emp in arr) { Console.WriteLine (" " + emp); } // Sort the employees by ZIP code and show the list. Console.WriteLine (" Sorted by ZIP code:"); arr = SortList (SortBy.ZIP); foreach (clsEmployee emp in arr) { Console.WriteLine (" " + emp); } } // Define a method that will create the proper delegate according to // the sort that is needed. static clsEmployee [] SortList (SortBy iSort) { clsEmployeeContainer.CompareItems sort = null; switch (iSort) { case SortBy.Name: sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByName); break; case SortBy.ID: sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByID); break; case SortBy.ZIP: sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByZip); break; } // Do the sort and return the sorted array to the caller. return (container.SortItems (sort, false)); } } public class clsEmployee : Component { // Define an employee class to hold one employee's information. public clsEmployee (string First, string Last, string Zip, int ID) { FirstName = First; LastName = Last; EmployeeID = ID; ZipCode = Zip; } public string FirstName; public string LastName; public string ZipCode; public int EmployeeID; // Define a method to sort by name static public int CompareByName (object o1, object o2) { clsEmployee emp1 = (clsEmployee) o1; clsEmployee emp2 = (clsEmployee) o2; return (String.Compare (emp1.LastName, emp2.LastName)); } // Define a method to sort by ZIP code static public int CompareByZip (object o1, object o2) { clsEmployee emp1 = (clsEmployee) o1; clsEmployee emp2 = (clsEmployee) o2; return (String.Compare (emp1.ZipCode, emp2.ZipCode)); } // Define a method to sort by employee ID number. static public int CompareByID (object o1, object o2) { clsEmployee emp1 = (clsEmployee) o1; clsEmployee emp2 = (clsEmployee) o2; return (emp1.EmployeeID - emp2.EmployeeID); } // Override ToString() for diagnostic purposes public override string ToString () { return (FirstName + " " + LastName + ", ZIP " + ZipCode + ", ID " + EmployeeID); } } // Derive a class to hold the clsEmployee objects public class clsEmployeeContainer { private Container cont = new Container(); public void Add (clsEmployee empl) { cont.Add (empl); } // Declare an array to return to the caller clsEmployee [] arrEmployee; // Declare a delegate to compare one employee object to another public delegate int CompareItems (object obj1, object obj2); // Define a sort function that takes a delegate as a parameter. The Reverse // parameter can be used to reverse the sort. public clsEmployee [] SortItems (CompareItems sort, bool Reverse) { // Get the clsEmployee objects in the container. ComponentCollection employees = cont.Components; // Create an array large enough to hold the references arrEmployee = new clsEmployee[employees.Count]; // Copy the collection into the reference. The Container class will not // let us sort the collection itself. employees.CopyTo (arrEmployee, 0); // Do a simple bubble sort. There are more efficient sorting algorithms, // but a simple sort is all we need. while (true) { int sorts = 0; for (int x = 0; x < arrEmployee.Length - 1; ++x) { int result; // Sort in the reverse order if if the Reverse parameter equals true if (Reverse == true) result = sort (arrEmployee[x + 1], arrEmployee[x]); else result = sort (arrEmployee[x], arrEmployee[x + 1]); // Reverse the two elements if the result is greater than zero if (result > 0) { clsEmployee temp = arrEmployee[x]; arrEmployee[x] = arrEmployee[x+1]; arrEmployee[x+1] = temp; ++sorts; } } // If we did no sorts on this go around, the sort is complete. if (sorts == 0) break; } // Return the sorted array to the caller. return (arrEmployee); } // Return the collection to the caller. public ComponentCollection GetEmployees () { return (cont.Components); } } }