Object.Equals() 是如何实现的 "in the end"?
How is Object.Equals() implemented "in the end"?
出于好奇,我想看看 Object.Equals()
方法是如何实现的。
所以我浏览了 source code of Object which finally led me to RuntimeHelpers.Equals()。但是RuntimeHelpers的Equals方法是在外部实现的,没有Dllimport属性。
在哪里可以找到 RuntimeHelpers.Equals()
的“外部”实现?
您会发现它已在运行时本身中实现。寻找这些 extern 方法的实现时,一个很好的切入点是 ecalllist.h。在这里我们发现:
FCFuncElement("Equals", ObjectNative::Equals)
所以它是由 ObjectNative::Equals
实现的,我们发现 in objectnative.cpp:
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 = pThisMT->GetBaseSize();
if(pThisMT == 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
出于好奇,我想看看 Object.Equals()
方法是如何实现的。
所以我浏览了 source code of Object which finally led me to RuntimeHelpers.Equals()。但是RuntimeHelpers的Equals方法是在外部实现的,没有Dllimport属性。
在哪里可以找到 RuntimeHelpers.Equals()
的“外部”实现?
您会发现它已在运行时本身中实现。寻找这些 extern 方法的实现时,一个很好的切入点是 ecalllist.h。在这里我们发现:
FCFuncElement("Equals", ObjectNative::Equals)
所以它是由 ObjectNative::Equals
实现的,我们发现 in objectnative.cpp:
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 = pThisMT->GetBaseSize();
if(pThisMT == 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