Thursday, July 23, 2015

.Equals != == ...?

Equality!


Confusing title huh? I found out recently that .Equals() doesn't always behave the same as ==. More specifically, I was trying to compare an Int32 (int) to an Int64 (long). It was a bit more complicated than that really, I needed to find items in a list of complicated objects that matched (just by this number) complicated objects of another type in another list, and I kept coming up with no matches. I knew I should have some, but the comparison was coming up false for everything! I had a check kind of like this:
return SomeObj.SomeIntProp.Equals(SomeOtherObj.SomeLongProp);

I didn't realize at the time I initially coded it that one was an Int32 and the other an Int64, but I didn't really think it mattered anyways. So I changed it to something like this just for giggles:
return SomeObj.SomeIntProp == SomeOtherObj.SomeLongProp;

And sure enough, my code was now getting back the correct number of true results that I thought it should! Just so you know, the reason is this: there are 2 overloaded versions of Int32.Equals. One accepts an int parameter (Int32), and the other an Object parameter. If you are comparing int to int, then you'll call the first method which checks that the numbers are the same. If you call .Equals and you don't pass an Int32 value, then you will end up using the 2nd version of the method which accepts an Object parameter and always returns false if the value isn't in fact an Int32 or something with an implicit conversion to Int32. No such implicit conversion exists for Int64 to Int32. Boom!

Here's a sample console app you can run to see this in action:

using System;

namespace BlogEquals
{
    class Program
    {
        static void Main(string[] args)
        {
            int int1 = 34;
            long long1 = 34;
            Console.WriteLine("int1 == long1: " + (int1 == long1).ToString());
            Console.WriteLine("int1.Equals(long1): " + int1.Equals(long1).ToString());
            Console.ReadKey();
        }
    }
}


 The output is this:


What's Next?

See for yourself what happens if the right-side of the comparison is an Int16...can you explain the result?

Resources

Int32.Equals

2 comments:

  1. Widening conversions... Interesting.
    I guess the == must perform widening conversions on the value with greater resolution (i.e. more bits).

    ReplyDelete
  2. Pretty much. You'll get an implicit conversion of the lower-resolution value (the int) to the same higher-resolution type (the long).

    ReplyDelete