2009-05-08

Someone I know recently got stung by this, so I thought I’d mention it...

static void Main(string[] args)
{
  int a = 1;
  int b = a;
  Console.WriteLine(AreSame(a, b).ToString());
  Console.ReadLine();
}

static bool AreSame(object a, object b)
{
  return a == b;
}


What’s the output to the console? Does a equal b? Even if you didn’t know the answer you will have guessed it is False otherwise this blog would be totally pointless!

It’s false because the parameter types of AreSame are both "object". For a value type such as "int" to be passed as an object it needs to be boxed, so a new object instance is created which stores the value "1", but this is done for both parameters so we end up with 2 new instances both holding the value 1.

1 equals 1 for value types but the default comparison for System.Object is to compare references. If they are not the exact same object (and in this case they are not) then the result is false. Now if we typecast both a and b back to integers this would pass, but the fact that we are using System.Object parameters suggests we don’t know the true type. Instead we need to use Object.Equals, because no matter what the original type is it should have a correct implementation of Equals().

static bool AreSame(object a, object b)
{
  if (a == null && b == null)
    return true;
  if (a == null || b == null)
    return false;
  return a.Equals(b);
}


So the moral of the story is this. If ever you are passed "object" references make sure you check for equality using Equals!

No comments: