42

I searched the source code of FCL, and I got confused that string.Equals() uses Object.ReferenceEquals(), and Object.ReferenceEquals() uses == operator to jugde. And then I can't find how the == operator is defined.

So where is the original operator defined?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
喵喵喵
  • 691
  • 7
  • 12
  • 5
    Im pretty sure its part of the C# language itself and not part of objects. – Nahum Dec 09 '15 at 07:11
  • 1
    it's feature derived from C# language. **By default, the operator == tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator == in order to gain this functionality.** - from [msdn](https://msdn.microsoft.com/en-US/library/ms173147(v=vs.80).aspx#Anchor_1) – Jenish Rabadiya Dec 09 '15 at 07:16

4 Answers4

26

This is an operator that the language uses to validate that two values are the same. When your code would be compiled this operator would be compiled appropriately in CIL and then when we will be executed by the CLR the two values would be compared to be checked if they are the same.

For instance, this is the CIL code for the Main method:

Enter image description here

that the compiler produces for the following program (it's a console application):

class Program
{
    static void Main(string[] args)
    {
        int a = 3;
        int b = 4;
        bool areEqual = a == b;
        Console.WriteLine(areEqual);
    }
}

Note the IL_0007 line. There a ceq instruction has been emitted. This is that you are looking for, the == operator.

Important Note

This is happening when the == is not overloaded.

Christos
  • 53,228
  • 8
  • 76
  • 108
18

When there isn't an overloaded == operator (as here), the compiler emits a ceq instruction. There's no more C# code to look at at this point.

Compares two values. If they are equal, the integer value 1 (int32) is pushed onto the evaluation stack; otherwise 0 (int32) is pushed onto the evaluation stack.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
5

Overloading operator== in C# is syntactic sugar for calling a static function. The overload resolution, like all overload resolution, happens based on the static type of the object, not the dynamic type. Let's look at Object.ReferenceEquals again:

public static bool ReferenceEquals (Object objA, Object objB) {
    return objA == objB;
}

Here, the static type of objA and objB is Object. The dynamic type can be anything; a string, some other user defined type, whatever; that does not matter. The determination of which operator== is called is determined statically when this function is compiled, so you always get the default, non-overloaded, built in language-supplied one. .NET could just have not had a ReferenceEquals and let users do ((object)a) == ((object)b), but having a specific named function to say what's going on improves clarity.

Object.Equals, on the other hand, is just a virtual function. As a result, which Equals is chosen is based on the dynamic type of the object to the left of the .Equals(, like any other virtual function call.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
4

ceq takes two values from the stack and gives results. If the result value is 1 then they are considered equal and 0 if they are not equal.

However, the == operator doesn't always get translated to ceq. Whether == in C# results in ceq depends on some more factors like are data types primitives or do they have custom == operators or are they references.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rahul Nikate
  • 6,192
  • 5
  • 42
  • 54