简体   繁体   English

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

[英]What is the default behavior of Equals Method?

Let A be a class with some members as x, y, z:设 A 是一个类,其中一些成员为 x、y、z:

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

A is an Object so it inherits the "Equals" functions defined in Object. A 是一个对象,因此它继承了对象中定义的“等于”函数。 What is the default behavior of this function?这个函数的默认行为是什么? Does it check for the equality of members or does it check for reference equality?它是检查成员的相等性还是检查引用的相等性?

The default implementation of Equals supports reference equality for reference types , and bitwise equality for value types . Equals 的默认实现支持引用类型的引用相等值类型的按位相等 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 http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

它会检查参考,除非您覆盖 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.我不确定在第一个代码片段的注释中描述的“加载器技巧”如何与在 C++ 代码中也有相同方法处理 ValueType 的事实相关。

https://source.dot.net/#System.Private.CoreLib/Object.cs,50 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 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/vm/ecalllist.h#L913我们可以看到它指向:

https://github.com/dotnet/runtime/blob/603ebe97e2202bfa81d26cda146bddd53fde7f6b/src/coreclr/src/classlibnative/bcltype/objectnative.cpp#L140 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM