Hi Guys
NP92 CompareTo()
Following program is executing well. I couldn’t understand the logic behind the CompareTo(). Anyone knows please explain.
Thank you
using System;
namespace ObjComp
{
// The iteration of the Car can be ordered
// based on the CarID.
public class Car : IComparable
{
// State data.
private int CarID;
private string petName;
// properties.
public int ID
{
get { return CarID; }
set { CarID = value; }
}
public string PetName
{
get { return petName; }
set { petName = value; }
}
// Constructor set.
public Car(int id, string name)
{
this.CarID = id;
this.petName = name;
}
// IComparable implementation.
int IComparable.CompareTo(object o)
{
Car temp = (Car)o;
if (this.CarID > temp.CarID)
return 1;
if (this.CarID < temp.CarID)
return -1;
else
return 0;
}
}
public class CarApp
{
public static int
{
// Make an array of Car types.
Car[] myAutos = new Car[5];
myAutos[0] = new Car(123, "Rusty");
myAutos[1] = new Car(6, "Mary");
myAutos[2] = new Car(6, "Viper");
myAutos[3] = new Car(13, "NoName");
myAutos[4] = new Car(6, "Chucky");
// Now, sort them using IComparable.
Array.Sort(myAutos);
// Dump sorted array.
Console.WriteLine("***** Here is the ordered set of cars *****");
foreach (Car c in myAutos)
Console.WriteLine("{0} {1}", c.ID, c.PetName);
return 0;
}
}
}
/*
***** Here is the ordered set of cars *****
6 Chucky
6 Mary
6 Viper
13 NoName
123 Rusty
*/
AlanPosted Oct 3, 2008, 9:45 AM
Sure, it's possible to raise the exception and then recover from it by changing your Main() method as follows. Notice that the ArgumentException causes an InvalidOperationException to be raised because the system was unable to compare two objects in the ArrayList. We therefore have to catch the 'outer' exception first and then access the 'inner' exceptions's Message property:
public static void Main()
{
ArrayList temperatures = new ArrayList();
// Initialize random number generator.
Random rnd = new Random();
// Generate 10 temperatures between 0 and 100 randomly.
for (int ctr = 1; ctr <= 10; ctr++)
{
int degrees = rnd.Next(0, 100);
Temperature temp = new Temperature();
temp.Fahrenheit = degrees;
temperatures.Add(temp);
}
temperatures.Add("Hello"); // add non-temparature object
// Sort ArrayList but catch 'outer' exception
try
{
temperatures.Sort();
}
catch(InvalidOperationException e)
{
Console.WriteLine(e.Message)
Console.WriteLine(e.InnerException.Message);
}
// remove offending item
temperatures.Remove("Hello");
// sort and display
temperatures.Sort();
foreach (Temperature temp in temperatures)
Console.WriteLine(temp.Fahrenheit);
}
Posted Oct 3, 2008, 10:17 AM
Thank you very much for help, Alan
Posted Oct 3, 2008, 8:21 AM
Following program is executing well. I wish to know whether it is possible to redesign the program so that it throws the exception (highlighted in yellow) as well. Anyone knows please help me.
using System;
using System.Collections;
public class Temperature : IComparable
{
// The temperature value
protected double temperatureF;
public int CompareTo(object obj)
{
if (obj is Temperature)
{
Temperature otherTemperature = (Temperature)obj;
return this.temperatureF.CompareTo(otherTemperature.temperatureF);
}
else
{
throw new ArgumentException("Object is not a Temperature");
}
}
public double Fahrenheit
{
get { return this.temperatureF; }
set { this.temperatureF = value; }
}
public double Celsius
{
get { return (this.temperatureF - 32) * (5 / 9); }
set { this.temperatureF = (value * 9 / 5) + 32; }
}
}
public class CompareTemperatures
{
public static void Main()
{
ArrayList temperatures = new ArrayList();
// Initialize random number generator.
Random rnd = new Random();
// Generate 10 temperatures between 0 and 100 randomly.
for (int ctr = 1; ctr <= 10; ctr++)
{
int degrees = rnd.Next(0, 100);
Temperature temp = new Temperature();
temp.Fahrenheit = degrees;
temperatures.Add(temp);
}
// Sort ArrayList.
temperatures.Sort();
foreach (Temperature temp in temperatures)
Console.WriteLine(temp.Fahrenheit);
}
}
// The example displays the following output to the console (individual
// values may vary because they are randomly generated):
// 2
// 7
// 16
// 17
// 31
// 37
// 58
// 66
// 72
// 95
AlanPosted Mar 30, 2008, 12:22 PM
The CarId field will always be set when the Car is object is created as a result of this line in the constructor:
this.CarID = id;
Posted Mar 30, 2008, 7:42 AM
AlanPosted Mar 30, 2008, 6:39 AM
The CompareTo() method is used to determine how objects of a class which implements IComparable (such as the Car class) can be compared to each other (by default) when a collection of those objects (such as an Array) is sorted.
For this to work properly, the 'int' return value of CompareTo() needs to be:
Less than zero:
If the current instance will sort lower in the order than the object 'o' passed to the method as an argument
Greater than zero:
If the current instance will sort higher in the order than 'o'.
Zero:
If the current instance will sort in the same position in the order as 'o' (in practice, of course, the sort method will place them adjacent to each other).
As the parameter is of type object, the first job is to cast that to its actual type, Car, and place the reference in the 'temp' variable
The current Car object is then compared to 'temp' using the CarId field. The idea is to sort Cars in ascending order of their CarIds.
So, if the current Car's CarId is greater than temp's, we want it to sort higher in the order and so return '1' which is greater than zero.
if the current Car's CarId is less than temp's, we want it to sort lower in the order and so return '-1' which is less than zero.
Otherwise, the CarIds must be the same and we return zero.
The Array.Sort() method then uses this default comparer to do the sorting.