Solution in English below.
En fin, me perdí el reto de la semana pasada, aunque tampoco me molesta mucho, ya que no conocía la solución y no tuve apenas tiempo libre para pensar en ella. La pregunta de esta semana es relativamente sencilla (aunque también era sencilla la última que contesté, y la compliqué de narices):
| Look at the following Code segment written in C#: ArrayList a = new ArrayList(); ArrayList b = new ArrayList();
a.Add(1); b.Add(1);
a.Add(2); b.Add(2.0);
Console.WriteLine( a[0] == b[0] ); Console.WriteLine( a[1] == b[1] );
What will be typed into the console? And WHY? Hopefully you will “play fair” and won’t type it in Visual Studio to see the output, you are in a job interview after all… |
Y la solución:
Both Console.WriteLine() statements will print 'false'.
The reason is that ArrayList internally holds objects, and when we insert an integer, which is a value type. As we are inserting a value type to a collection which holds reference types, Boxing comes into play. This is what it is really happening behind the scenes when we call the ArrayList.Add() method:
- A new object is created in the managed heap
- The the integer is copied from the stack to the memory location of the newly created object
- The object, which now holds the integer, is inserted in the array list.
So, when we access the ArrayList with the indexer it obviously returns the object it was previously inserted, so what the equality operator is actually comparing two different objects, created during the Add() method call. As they are two different objects and as the == operator implementation for object types compares references, the comparison returns false.
What could be more puzzling is that if we use the Object.Equals() method, we get what it could be the correct expected solution:
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();
a.Add(1);
b.Add(1);
a.Add(2);
b.Add(2.0);
Console.WriteLine( a[0].Equals( b[0] ) );
Console.WriteLine( a[1].Equals( b[1] ) );
The above code prints 'true' and 'false'
Why Equals compares the values and not the reference? After all, the default implementation of Equals, also compares references according to the documentation...
The reason is that Object.Equals() is a virtual method which is overwritten in ValueTypes to use a bitwise comparison. As the integer -which is an alias for Int32, which derives from ValueType- is boxed inside an Object, and Object is the base class for all types in .NET CTS (and that of course includes ValueType ), a polimorfic call to integer.Equals() its made, which compares values, and not references.
So the first comparison is true, as both values are the same, but the second comparison keeps returning false, because value 2 and value 2.0 were two different types (integer and double respectively) in the first place.