.NET: Where is the default implementation for "==" op_Equality () for value types?
I went to .NET Reflector and noticed that there is an explicit overload of the "==" operator for reference types like "String" for example:
typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)
returns: System.Reflection.MethodInfo for the "==" operator.
Due to its implementation, you cannot do things like:
if("hi" == 3) // compiler error, plus code would throw an exception even if it ran)
However, the same works for value types:
if((int)1 == (float)1.0) // correctly returns true
if((int)1 == (float)1.2) // correctly returns false
I'm trying to figure out how .NET handles the type conversion process, so I looked for an op_Equality () implementation in .NET Reflector, but "int" doesn't have that.
typeof(int).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)
returns null.
So where is the default implementation for the "==" operator for value types? I would like it to be called reflection:
public bool AreEqual(object x, object y)
{
if(x.GetType().IsValueType && y.GetType().IsValueType)
return x == y; // Incorrect, this calls the "object" equality override
else
...
}
Edit # 1:
I tried this but it didn't work:
(int)1 == (float)1; // returns true
System.ValueType.Equals( (int)1, (float)1 ); // returns false
Edit # 2:
And tried this but didn't like:
object x = (int)1;
object y = (float)1.0;
bool b1 = (x == y); // b1 = false
bool b2 = ((ValueType)x).Equals(y); // b2 = false
I believe this .Equals operator in ValueType is not working due to checking this type (broke from .NET Reflector):
ValueType.Equals(object obj)
{
...
RuntimeType type = (RuntimeType) base.GetType();
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type)
{
return false;
}
...
a source to share
What you are looking for is ValueType.Equals
In many cases, this is simply a bit-by-bit comparison. In some cases though, it will use reflection to validate fields.
EDIT
You are confusing how C # compares value types and how .Net compares value types. ValueType.Equals is a function in .Net used to compare value type objects that have the same type. C # will emit code that ultimately calls this function. But this is not called "int" and "float". Instead, it first converts both of them to a type that does not lose precision for the (double) value, and then compares the resulting double values. This is why you see the difference in behavior.
a source to share
Where is the default implementation for
==
op_Equality
for value types used?
There is no default for value types ==
. Try to write your own value type
struct JustAnotherValueType
{
public readonly int Field;
public JustAnotherValueType(int f) { Field = f; }
}
Make two values x
and y
your type. Try to talk x == y
to them. It won't compile. You can tell
(object)x == (object)y
but it will do boxing on x
(let it come out in box 1) and boxing on y
(box 2), and then do the comparison in two blocks. Hence, it will always return false. And so it's useless, and the reason why the overload is ==(object x, object y)
not automatically chosen when used ==
between the two JustAnotherValueType
.
So what happens to int
and float
? You can compare them to ==
in C # and they don't have a method op_Equality
?! The explanation is that these overloads are defined by the C # language specification . See Sections Integer Comparison Operators and Floating Point Comparison Operators.
Thus, the fact is that while these operators do not exist as members of .NET structures, the C # language specification defines them, and the C # compiler must emit some valid IL to mimic their behavior.
By the way, it System.Object
also does not op_Equality
. It is also only defined by C #. See Section Equality Operators of Reference Type. Note that there System.Object
is a method ReferenceEquals
that the compiler can choose to translate this overload ==
to. Also note that this section of the spec is limiting so it x == y
will never box on x
or y
.
What about value types such as DateTime
, TimeSpan
and Guid
, which are not mentioned in the C # spec, but for which it is legal to use ==
? Answer: These do have a member op_Equality
.
Conclusion. The C # Language Specification defines many overloads ==
that a C # implementation must have, and some of these overloads include int
and float
and object
.
Note. A virtual instance method is Equals(object)
defined in object
and inherited by all value types. For structures that do not override this method, use override
in System.ValueType
. It is compared by value. So, x
and y
as above x.Equals(y)
will work fine. Equals
- virtual instance method. On the other hand, it ==
is a method static
"that performs overload resolution based on the compile-time types of the two operands (no" virtual dispatch ").
a source to share
I am assuming you are looking for ValueType.Equals (an obj object) that inherits to your structs. It uses reflection to compare all fields.
a source to share
My answer to another question provides a rotor implementation. The actual code is implemented in the CLR as native code.
In particular:
// Compare the contents (size - vtable - sink block index).
BOOL ret = memcmp(
(void *) (pThisRef+1),
(void *) (pCompareRef+1),
pThisRef->GetMethodTable()->GetBaseSize() - sizeof(Object) - sizeof(int)) == 0;
a source to share