What is the default behavior of Equals Method?

it checks for reference unless you override equals


For "I want to know exactly how it works" kind of people below is the source code reference. I'm not sure though how the "loader trick" described in the comment in the first code fragment relates to the fact that in C++ code there is also handling for a ValueType in the same method.

https://source.dot.net/#System.Private.CoreLib/Object.cs,50

// Returns a boolean indicating if the passed in object obj is
// Equal to this.  Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
public virtual bool Equals(object? obj)
{
    return RuntimeHelpers.Equals(this, obj);
}

https://source.dot.net/#System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs,105

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern new bool Equals(object? o1, object? o2);

Looking at https://github.com/dotnet/runtime/blob/603ebe97e2202bfa81d26cda146bddd53fde7f6b/src/coreclr/src/vm/ecalllist.h#L913 we can see it points to:

https://github.com/dotnet/runtime/blob/603ebe97e2202bfa81d26cda146bddd53fde7f6b/src/coreclr/src/classlibnative/bcltype/objectnative.cpp#L140

FCIMPL2(FC_BOOL_RET, ObjectNative::Equals, Object *pThisRef, Object *pCompareRef)
{
    CONTRACTL
    {
        FCALL_CHECK;
        INJECT_FAULT(FCThrow(kOutOfMemoryException););
    }
    CONTRACTL_END;

    if (pThisRef == pCompareRef)
        FC_RETURN_BOOL(TRUE);

    // Since we are in FCALL, we must handle NULL specially.
    if (pThisRef == NULL || pCompareRef == NULL)
        FC_RETURN_BOOL(FALSE);

    MethodTable *pThisMT = pThisRef->GetMethodTable();

    // If it's not a value class, don't compare by value
    if (!pThisMT->IsValueType())
        FC_RETURN_BOOL(FALSE);

    // Make sure they are the same type.
    if (pThisMT != pCompareRef->GetMethodTable())
        FC_RETURN_BOOL(FALSE);

    // Compare the contents (size - vtable - sync block index).
    DWORD dwBaseSize = pThisRef->GetMethodTable()->GetBaseSize();
    if(pThisRef->GetMethodTable() == g_pStringClass)
        dwBaseSize -= sizeof(WCHAR);
    BOOL ret = memcmp(
        (void *) (pThisRef+1),
        (void *) (pCompareRef+1),
        dwBaseSize - sizeof(Object) - sizeof(int)) == 0;

    FC_GC_POLL_RET();

    FC_RETURN_BOOL(ret);
}
FCIMPLEND

The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.

http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

Tags:

C#