Fun with Equality Follow up…


Some great answers to my recent quiz… I particularly love the Nullable<T> and string interning usage.. very nice!


 


The question again was:


Find examples for each of the following:


            Question 1: x == y && !x.Equals(y)


            Question 2: x != y && x.Equals(y)


            Question 3: x ==y doesn’t even compile


            Question 4: x == y && (object)x != (object)y


 


Here are the answers I had in mind…


 


        public static void Question1()


        {


            int x = 1; byte y = 1;


            Console.WriteLine(x == y && !x.Equals(y));


        }


Question 1 boxes y and calls Int32.Equals() on it.  The first line of Int32.Equals check to see if they are of the same type, they are not this is an int while the object is of type byte, so it returns false.


 


        public static void Question2()


        {


            string x = “hello”; object y = string.Copy(x);


            Console.WriteLine(x != y && x.Equals(y));


        }


Question2 plays off the difference between reference equality and value equality. x != y uses reference equality.. are these two values stored at the same location? While string overloads the .Equals() method to be value equality (that is do these two values have the same contents).  Notice it is tricky because the C# compiler defines == and != on strings to be value equality as well, but in this case it is between a string and an object.  Also note that we have to copy the string, we can’t just use a literal string of the same value because of string interning they’d have the same location.  


 


        public static void Question3()


        {


            string x = null; Type y = null;


            Console.WriteLine(x == y);


        }


 


Question3 is a bit of a trick… == is not defined between string and Type so this will not compile.  


 


        public static void Question4()


        {


            int x = 1; int y = 1;


            Console.WriteLine(x == y && (object)x != (object)y);


        }


 


Question4 is the basics of boxing.  x and y each box into their own instance stored in different locations so the reference comparison their returns false.  


 


 


Astute readers will notice that on V2.0, Question 1 actually prints true not false.  The reason is that we added an overload Int32.Equals (int value).  So rather the boxing to call the default equals method, the compiler widens y to an int and calls the strongly typed Equals method which does the right thing.    Notice it is simple enough to make this pass on V2.0 as well…


        public static void Question1()


        {


            int x = 1; float y = 1;


            Console.WriteLine(x == y && !x.Equals(y));


        }


 


 


Thanks for playing!


 


 Fun with Equality Follow up…

Comments (3)

  1. public static void Question3()

    {

    string x = null; Type y = null;

    Console.WriteLine(x == y);

    }

  2. TAG says:

    Here is one more "funny-buggy" code:

    class Boo {

    public void DoFoo() { }

    public static bool operator==(Boo a, Boo b) { return false; }

    public static bool operator !=(Boo a, Boo b) { return true; }

    }

    static void Main(string[] args) {

    Boo boo = null;

    if (boo != null) {

    boo.DoFoo();

    }

    }

    So – never trust operators 🙁

  3. TheMuuj says:

    Never trust operators?

    I could say the same of any method. I could write an override of Equals that randomly returns true or false, and that would be just as bad or worse than operator overloading.

    However, operators *can* be used for some nasty things. Imagine overloading the unary + operator to actually do something. I doubt anybody would think that y would be different than x:

    Foo x = new Foo();

    Foo y = +x;