Quiz about C# and object equality.


Here’s a silly little C# pop-quiz about equality. Given a local variable x declared of type ‘int’, what do the following C# expressions evaluate to?

  1. x == x
  2. (object) x == (object) x
  3. (System.Object) x == (System.Object) x
  4. (int) (object) x == (int) (object) x
  5. (float) x == (float) x
  6. (int) x == (int) x
  7. (int) x == (float) x
  8. (float) (int) x == (int) (float) x
  9. (System.Int32) x == (System.Int32) x
  10. x.ToString() == x.ToString()
  11. (object) x.ToString() == (object) x.ToString()

For bonus points, identify any additional work in each expression that’s not directly comparing equality of two integers.

 

[Update] To simplify, assume an unchecked context (which is the default). I’ve posted the answers here

[Update] If you think changing operator== to Object.Equals will solve all your problems, try this related quiz here .

Comments (13)

  1. David says:

    How would #8 function in a 64-bit environment?

  2. Haven’t tried these, but I’ll venture a guess:

    1. x == x. true. no extra work.

    2. (object) x == (object) x. false. Two different objects created for boxing, integers are boxed and objects are compared.

    3. (System.Object) x == (System.Object) x. false. Same as previous.

    4. (int) (object) x == (int) (object) x. true. Two objects are created for boxing, integers are boxed, objects are unboxed to integers on stack and are compared.

    5. (float) x == (float) x. false. I can’t explain it really, but there has to be something that goes wrong with floating point numbers. It’s never quite what you expect it to be.

    6. (int) x == (int) x. true. no extra work.

    7. (int) x == (float) x. false. A floating point variable on stack gets its value from the integer. The integer in left-x is then converted to float for comparison (my guess is that the ‘more complicated number’ wins) and comparison is like in #5.

    8. (float) (int) x == (int) (float) x. false. right x is converted to float then to integer (both variables on stack). left x is converted to float (on stack). from then it’s like #8.

    9. (System.Int32) x == (System.Int32) x. true. no extra work.

    10. x.ToString() == x.ToString(). true. A string is created by each integer, then both are string-compared.

    11. (object) x.ToString() == (object) x.ToString(). true. Boxing like in #2, then the overridden ToString is called and comparison is like in #10.

    Again, just my guesses.

  3. Mike Stall says:

    I’ve gotten a few responses. I’ll keep the comments that provide answers or hints moderated for now as to not give away any answers yet (since people may be tainted by accidentally seeing the comments when reading the quiz above).

  4. David says:

    I’m confused…you are hiding the answers? You already posted them. That is what that link is.

  5. Tim says:

    Pretty Creative Mike! I saw two big themes (keeping it simple): (1) Boxing, (2) Floating point precision. I first assumed that all value-type and string comparisons would be true, so the three being cast with (object) would be false. I then assumed that because we start with int, there shouldn’t be floating point errors, so I got tripped up on:

    (float) (int) x == (int) (float) x

    Your explanation makes sense. Neat

    Tim

  6. Tim Stall says:

    Can you comment on using the checked and unchecked keywords here? For example, if I set x = int.MaxValue and replace #8 to:

    checked(

    (float) (int) x == (int) (float) x

    );

    it throws an Arithmetic operation resulted in an overflow. If I omit the checked keyword, there is no exception.

    Do you recommend always using checked() when doing explicit conversion? I checked fxcop, and there was no rule on this.

  7. Jeff says:

    This is why you should never write code like this. If it isn’t obvious to almost any user reading the code, that’s a bad thing. 🙂

  8. Ben says:

    Well, Jeff, unless you want to artificially boost your job security. 😉

  9. Mike Stall says:

    Jeff – I totally agree that code should be clear and obvious. However, folks may run into a few issues:

    1) developers may wrongly think something’s obvious. All of the expressions above are very simple and innocent, so devs may think they’re obvious. Yet I haven’t got 1 correct answer.

    2) I think these sort of expressions can naturally come up. For eg, anybody that writes their own general collection may hit these.

    I think avoiding that confusion is part of the motivation for having System.Object.Equals().

  10. Mike Stall says:

    David – It turns out all of these are agnostic to a 64-bit envirornment. ‘int’ and ‘float’ are still 4 bytes there.