-2

I am implmenting the IComparable to sort like typed objects. My question is why does it cast type person to int32? The array's Sort() seems to cast each type in the array to the type that I am using for comparison.

Comparable:

public class Person:IComparable 
{
   protected int age;

   public int Age { get; set; }

   public int CompareTo(object obj)
   {
       if(obj is Person)
       {
           var person = (Person) obj;
          return age.CompareTo(person.age);
       }
       else
       {
           throw new ArgumentException("Object is not of type Person");
       }
   }
}

}

class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Person();
        Person p2 = new Person();
        Person p3 = new Person();
        Person p4 = new Person();

        ArrayList array = new ArrayList();

        array.Add(p1.Age = 6);
        array.Add(p2.Age = 10);
        array.Add(p3.Age = 5);
        array.Add(p4.Age = 11);

        array.Sort();

        foreach (var list in array)
        {
            var person = (Person) list; //Cast Exception here.

            Console.WriteLine(list.GetType().ToString()); //Returns System.Int32
        }
        Console.ReadLine();


    }
Nick
  • 19,198
  • 51
  • 185
  • 312
  • BTW: If you're on .Net 3.5, you don't need to use Sort() and IComparable. There is a new extension method called OrderBy that is a lot easier to use than Sort. – Mark Byers Dec 12 '09 at 19:11
  • 4
    If he's on .Net 3.5 (or 2.0) he really shouldn't use ArrayList, but List. He wouldn't have had this issue if he did (he would get a compilation error and it would probably figure out the problem). – Doron Yaacoby Dec 12 '09 at 19:14
  • Why don't you use the generic `List` and `IComparable`? – thecoop Dec 12 '09 at 19:15
  • Also, the use of generics would have been revealing here. It's better to use generic typing were possible if you're using .Net 2.0 or higher – Mike Dec 12 '09 at 19:17
  • Thanks for the tips.. I probably would use a IList in practice. This is just a little experiment to get comfotable with IComparable – Nick Dec 12 '09 at 19:24
  • Whenever there is a generic and a non-generic interface, you should implement both, but the non-generic implementation should just cast the object to the relevant type and pass it on to the generic implementation. I don't know if I've explained that very well. I'll add an answer. – Mark Rendle Dec 12 '09 at 19:32

4 Answers4

11

Your line:

array.Add(p1.Age = 6)

adds the result of the statement p1.Age = 6 to the ArrayList. This is the int value 6. Nothing to do with IComparable or Sort.

David M
  • 71,481
  • 13
  • 158
  • 186
8

The best way to implement IComparable is to implement IComparable<T> and pass the calls on to that implementation:

class Person : IComparable<Person>, IComparable
{
  public int Age { get; set; }

  public int CompareTo(Person other)
  {
    // Should be a null check here...
    return this.Age.CompareTo(other.Age);
  }

  public int CompareTo(object obj)
  {
    // Should be a null check here...
    var otherPerson = obj as Person;
    if (otherPerson == null) throw new ArgumentException("...");
    // Call the generic interface's implementation:
    return CompareTo(otherPerson);
  }
}
Mark Rendle
  • 9,274
  • 1
  • 32
  • 58
  • You may want to add if(other == null) return 1; in your CompareTo – tymtam Jul 05 '11 at 09:15
  • @Tymek, good point, this implementation doesn't deal gracefully with objects of other types (heterogeneous collections) or even nulls of the same type. – Constantin Jul 15 '11 at 07:24
4

You're not adding the Persons to the array.

p1.Age = 6

is an assignment, and it returns whatever was assigned to the variable/property (in this case, 6).

You need to do the assignments before putting the Persons into the array.

If you're only looking to put elements of a single type into a collection, you want to use a typed collection rather than an untyped one. This would have caught the problem immediately.

Anon.
  • 58,739
  • 8
  • 81
  • 86
1

You are adding person.Age to your arraylist, and person.Age is an int.
You should do something like

Person p1 = new Person(){Age=3};
array.Add(p1);
Mathias
  • 15,191
  • 9
  • 60
  • 92