14

What is the difference between the evaluation of == and Equals in C#?

For Ex,

if(x==x++)//Always returns true

but

if(x.Equals(x++))//Always returns false 

Edited:

     int x=0;
     int y=0;

     if(x.Equals(y++))// Returns True
Aditya Singh
  • 9,512
  • 5
  • 32
  • 55
  • 12
    @ Moderators: Read the complete question before closing any question. If you have the rights to close any question, use them at right place. – Aditya Singh Oct 06 '10 at 11:12
  • 4
    @ Jørn Schou-Rode, Arcturus, Oded, Pandiya Chendur, GregS: Since you all have voted to close this question. Please provide me a proper answer for the question asked above or reopen the question. – Aditya Singh Oct 06 '10 at 17:00

2 Answers2

13

According to the specification, this is expected behavior.

The behavior of the first is governed by section 7.3 of the spec:

Operands in an expression are evaluated from left to right. For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. This is separate from and unrelated to operator precedence.

Thus in x==x++, first the left operand is evaluated (0), then the right-hand is evaluated (0, x becomes 1), then the comparison is done: 0 == 0 is true.

The behavior of the second is governed by section 7.5.5:

  • If M is an instance function member declared in a value-type:
    • E is evaluated. If this evaluation causes an exception, then no further steps are executed.
    • If E is not classified as a variable, then a temporary local variable of E’s type is created and the value of E is assigned to that variable. E is then reclassified as a reference to that temporary local variable. The temporary variable is accessible as this within M, but not in any other way. Thus, only when E is a true variable is it possible for the caller to observe the changes that M makes to this.
    • The argument list is evaluated as described in §7.5.1.
    • M is invoked. The variable referenced by E becomes the variable referenced by this.

Note that value types are passed by reference to their own methods.

Thus in x.Equals(x++), first the target is evaluated (E is x, a variable), then the arguments are evaluated (0, x becomes 1), then the comparison is done: x.Equals(0) is false.

EDIT: I also wanted to give credit to dtb's now-retracted comment, posted while the question was closed. I think he was saying the same thing, but with the length limitation on comments he wasn't able to express it fully.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
4

Order of evaluation. ++ evaluates first (second example). But in the first example, == executes first.

Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • 2
    Wow! I cant believe my eyes... I will get back to you – Aliostad Oct 06 '10 at 12:02
  • 2
    Sure Anytime.... but the output will remain the same, even if you come after one year...:) – Aditya Singh Oct 06 '10 at 17:02
  • 2
    I think the general idea of this answer is correct, for the 2nd and 3rd example: 1. The parameter to Equals is evaluated, this will "reserve" 0 as the value parameter, but it will also increment x by 1. 2. The Equals is performed. if x=0, then x.Equals(x++) becomes 1.Equals(0). The difference between the 1st and 2nd example is that == is performed before x itself is set to x+1. If you overload the operators on a struct and debug you'll see that it will actually step into ++ before ==, but it doesn't do anything with the result from ++ until after the expression in which it occurs is evaluated. – Bubblewrap Oct 07 '10 at 08:15
  • 1
    It's not order of evaluation, exactly. The target of the Equals method is evaluated first. But the result isn't the value of x (0), it's the address of x, because methods on value types receive a "this" pointer, not the value of the target. – Ben Voigt Oct 07 '10 at 21:14