Jeff Garoutte

c# .net and anything else that happens across my desk

Variable boxing and == vs. Equals

Let's take a moment and think about exactly how boxed variables work when checking to see if they are equal.

Here is a little Console application to do a quick comparison of how the Equals function and == operator work.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VariableBoxEqualityTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 1;
            int y = 1;

            test(x, y);
           
            x = 2;
            y = 3;
            test(x, y);

            x = 5;
            test(x);
            Console.ReadKey();
        }

        private static void test(int x)
        {
            Console.WriteLine();
            Console.WriteLine("Testing with x=y={0}", x);
            DoTests(x, x);
            object ox = x;
            ObjectRefIsEquals(ref ox, ref ox);
            ObjectRefIsEqual(ref ox, ref ox);

            Console.WriteLine();
            ObjectIsEqual(ox, ox);
        }

        private static void test(int x, int y)
        {
            Console.WriteLine();
            Console.WriteLine("Testing with x={0} and y={1}", x, y);
            DoTests(x, y);
            object ox = x;
            object oy = y;
            ObjectRefIsEquals(ref ox, ref oy);
            ObjectRefIsEqual(ref ox, ref oy);
        }

        private static void DoTests(int x, int y)
        {
            object ox = x;
            object oy = y;
            ObjectIsEqual(ox, oy);
            ObjectIsEquals(ox, oy);
            intIsEqual(x, y);
            intIsEquals(x, y);
        }

        public static void intIsEqual(int x, int y)
        {
            Console.WriteLine("(int)x==(int)y : {0}", x == y);
        }

        public static void intIsEquals(int x, int y)
        {
            Console.WriteLine("((int)x).Equals((int)y) : {0}", x.Equals(y));
        }

        public static void ObjectIsEqual(object x, object y)
        {
            Console.WriteLine("(object)x==(object)y : {0}", x == y);
        }

        public static void ObjectIsEquals(object x, object y)
        {
            Console.WriteLine("((object)x).Equals((object)y) : {0}", x.Equals(y));
        }

        public static void ObjectRefIsEquals(ref object x, ref object y)
        {
            Console.WriteLine("((ref object)x).Equals((ref object)y) : {0}", x.Equals(y));
        }

        public static void ObjectRefIsEqual(ref object x, ref object y)
        {
            Console.WriteLine("((ref object)x)==((ref object)y) : {0}", x==y);
        }
    }
}

Now here are the results....

Console application result.

There are four groups of results above, let us about the first result in each set (and the only one in the last set).

(object)x==(object)y : False.  With the exception of the last result this test was always False.  Why?  Because == was checking to see if the object was the same object, not if the values were the same.  In the first 3 sets x and y were boxed into the ox and oy objects before the call to ObjectIsEqual.  The forth set passed ox in twice ObjectIsEqual(ox, ox); .

Even when the values of x and y are the same the act of boxing them makes the objects different, and therefore not equal using the == operator.

If you box the same variable a second time the two objects will not be equal even though they are the same variable. 

Here's a code change you can use to easily test that if you like...

 private static void test(int x)
        {
            Console.WriteLine();
            Console.WriteLine("Testing with x=y={0}", x);
            DoTests(x, x);
            object ox = x;
            ObjectRefIsEquals(ref ox, ref ox);
            ObjectRefIsEqual(ref ox, ref ox);

            Console.WriteLine();
            ObjectIsEqual(ox, ox);

            Console.WriteLine();
            object oy = x;
            ObjectIsEqual(ox, oy);
        }

the 2nd test in in set is the ((object)x).Equals((object)y) test.  It passed in the 1st and 3rd set while failing in the 2nd.  Which is what we would expect since 1=1, 2!=3 and 5=5.  So the Equals function on a boxed (or unboxed) int works.

The 3rd and 4thtests in each set  are the same functions from the first two tests except on unboxed ints.  Both the == operator and the Equals method were correct in little tests. (If they were Id be worried).

the 5th and 6th test in each set are the same as the first two expect we are passing the objects in by reference.  We would expect the same results...but no, the in the 3rd set (object)x==(object y) was false and ref object x==ref object y was true.... what happened?

What happened?

The 1st test boxes x twice and passes it into the test. So the objects are not the same and it fails.

The 6th test boxes x once and pass in the same object twice so they match.  It has nothing to do with them being passed as a ref.   Here's another code snip you can use to test it.

private static void test(int x)
        {
            Console.WriteLine();
            Console.WriteLine("Testing with x=y={0}", x);
            DoTests(x, x);
            object ox = x;
            ObjectRefIsEquals(ref ox, ref ox);
            ObjectRefIsEqual(ref ox, ref ox);

            Console.WriteLine();
            ObjectIsEqual(ox, ox);

            Console.WriteLine();
            object oy = x;
            ObjectIsEqual(ox, oy);

            Console.WriteLine();
            ObjectRefIsEqual(ref ox, ref oy);
        }

My point is, when you box a variable you have to pay attention to how you work with it while it is boxed.  I have seen code where it was assumed that x==y is true when x and y both equal 1 and they are boxed as an object.

kick it on DotNetKicks.com

Posted: Jun 18 2009, 10:04 by jeff | Comments (3) RSS comment feed |
Filed under: General | Research
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Comments

jeffgaroutte.net said:

pingback

Pingback from jeffgaroutte.net

Using an Object for an Id

# June 20 2009, 19:00

snoozer pet carrier United States said:

snoozer pet carrier

Great Work !

Regards
Parry

# December 14 2009, 20:46

how to sell on amazon United States said:

how to sell on amazon

Great post! I am just starting out in community management/marketing media and trying to learn how to do it well - resources like this article are incredibly helpful. As our company is based in the US, it?s all a bit new to us. The example above is something that I worry about as well, how to show your own genuine enthusiasm and share the fact that your product is useful in that case.

# January 10 2010, 21:42

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
Loading