Equals方法的默认行为是什么?

时间:2010-04-13 18:59:19

标签: c#

设A是一个类,其中一些成员为x,y,z:

Class A {
  int x;
  int y;
  String z;
  ...
}

A是一个Object,因此它继承了Object中定义的“Equals”函数。 这个函数的默认行为是什么?它是检查成员是否相等还是检查引用相等性?

3 个答案:

答案 0 :(得分:49)

  

Equals的默认实现   支持引用相等   引用类型按位相等   对于值类型。参考平等   表示对象引用   比较指的是同一个对象。   按位相等意味着对象   被比较的具有相同的二进制   表示。

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

答案 1 :(得分:6)

除非你重写等于

,否则它会检查引用

答案 2 :(得分:0)

对于“我想确切地知道它是如何工作的”,以下人员是源代码参考。我不确定第一个代码片段中的注释中描述的“加载器技巧”如何与以下事实有关:在C ++代码中,也使用相同的方法处理ValueType。

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);

https://github.com/dotnet/runtime/blob/603ebe97e2202bfa81d26cda146bddd53fde7f6b/src/coreclr/src/vm/ecalllist.h#L913 我们可以看到它指向:

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