Implementing IComparable
Asked Answered
M

4

-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();


    }
Michaelemichaelina answered 12/12, 2009 at 19:9 Comment(6)
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.Coly
If he's on .Net 3.5 (or 2.0) he really shouldn't use ArrayList, but List<Person>. He wouldn't have had this issue if he did (he would get a compilation error and it would probably figure out the problem).Underpin
Why don't you use the generic List<T> and IComparable<T>?Katzenjammer
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 higherCalycle
Thanks for the tips.. I probably would use a IList<T> in practice. This is just a little experiment to get comfotable with IComparableMichaelemichaelina
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.Indorse
A
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.

Astrobiology answered 12/12, 2009 at 19:11 Comment(0)
I
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);
  }
}
Indorse answered 12/12, 2009 at 19:9 Comment(2)
You may want to add if(other == null) return 1; in your CompareToRetrogression
@Tymek, good point, this implementation doesn't deal gracefully with objects of other types (heterogeneous collections) or even nulls of the same type.Cleptomania
C
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.

Cuenca answered 12/12, 2009 at 19:14 Comment(0)
S
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);
Steele answered 12/12, 2009 at 19:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.