Object等 - 什么纯粹的对象或引用类型不重写等于基本逻辑? [英] Object Equals - whats the basic logic for pure objects or reference types that don't override Equals?

查看:165
本文介绍了Object等 - 什么纯粹的对象或引用类型不重写等于基本逻辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来到这里后,读<一href="http://stackoverflow.com/questions/3678792/are-string-equals-and-operator-really-same">this我没有找到相关的答案 - 所以请直到你读了整个问题没有标记这是一个重复的

I got here after reading this and I didn't find a relevant answer - So please don't mark this as a duplicate until you read the whole question.

我一直在使用反射镜,看着的Object.Equals 。什么我看到的是:

I've been using a reflector and looked into Object.Equals.What I saw is:

[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public virtual bool Equals(object obj)
{
    return RuntimeHelpers.Equals(this, obj);
}

RuntimeHelpers.Equals 是这样的:

// System.Runtime.CompilerServices.RuntimeHelpers
/// <summary>Determines whether the specified <see cref="T:System.Object" /> instances are considered equal.</summary>
/// <returns>true if the <paramref name="o1" /> parameter is the same instance as the <paramref name="o2" /> parameter, or if both are null, or if o1.Equals(o2) returns true; otherwise, false.</returns>
/// <param name="o1">The first object to compare. </param>
/// <param name="o2">The second object to compare. </param>
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
public new static extern bool Equals(object o1, object o2);

现在我看不到 RuntimeHelpers.Equals 的实施,而是由描述,如果两个对象是不一样的实例,并且不为空,它会调用在的Object.Equals 再次方法,我会进入一个循环(我说的是纯对象)。

Now I can't see the implementation of RuntimeHelpers.Equals but by the description, if both objects aren't the same instance and aren't null it will call the object.Equals method again and I'd get into a loop (I'm talking about pure objects).

当我说纯粹的对象我的意思是这样的:

When I say pure objects I mean something like this:

object pureObj1 = new object();
object pureObj2 = new object();
bool areEql = pureObj1.Equals(pureObj2);

通过的文件,这应该叫的Object.Equals ,并获得 recusive计算器。我想也许文件是错误的,这种检查引用相等作为基本对象 - 但我想是肯定

By documentation this should call Object.Equals and get a recusive stackoverflow. I guess maybe the documentation is wrong and this checks reference equality for basic objects - but I wanted to be sure.

底线:
在比较两个纯对象通过等于(例如:未铸造字符串转换成对象)通话 - 它是如何确定它们是否相等? - 如果我不覆盖等于的方法,我称之为等于的两个对象,会发生什么?
丁香反正是有,我可以看到 RuntimeHelpers.Equals 源$ C ​​$ C?

Bottom line:
When comparing two pure objects(e.g. not casting a string into on object) via an Equals call - how does it determine if they are equal? - What happens if I don't override the Equals method and I call Equals on two objects?
P.s. is there anyway that I can see the RuntimeHelpers.Equals source code?

推荐答案

的Object.Equals(对象) 包括这在一些细节方法(对象)> MSDN的页面。具体而言,对于引用类型的默认实现为引用相等。参见注意事项对于继承者的表是最直接的。

MSDN's page on object.Equals(object) covers this in some detail. Specifically, the default implementation for reference types is reference equality. The table in the section "Notes for Inheritors" is the most direct.

引用相等;相当于调用Object.ReferenceEquals。

Reference equality; equivalent to calling Object.ReferenceEquals.

MSDN的页面上 RuntimeHelpers.Equals(对象,对象) 不说,的Object.Equals(对象)是所谓的情况下,其参数不引用平等的,也不是零。这可以证明是错误实际上表现出的行为是 RuntimeHelpers.Equals(对象,对象)永远不会调用的Object.Equals(对象)

MSDN's page on RuntimeHelpers.Equals(object,object) does say that Object.Equals(Object) is called in the case that its arguments are not reference equal and neither is null. This is demonstrably false; the behavior actually exhibited is that RuntimeHelpers.Equals(object,object) never calls Object.Equals(Object).

例如,该LINQPad脚本:

For example, this LINQPad script:

void Main()
{
    object left = new Foo();
    object right = new Foo();
    left.Equals(right).Dump();
    RuntimeHelpers.Equals( left, right ).Dump();
    left = new Bar();
    right = new Bar();
    left.Equals(right).Dump();
    RuntimeHelpers.Equals( left, right ).Dump();
    left = new Baz();
    right = new Baz();
    left.Equals(right).Dump();
    RuntimeHelpers.Equals( left, right ).Dump();
    left = new Qux();
    right = new Qux();
    left.Equals(right).Dump();
    RuntimeHelpers.Equals( left, right ).Dump();
}

private class Foo {}

private class Bar {
    public override bool Equals(object obj) { 
        "Bar.Equals() called".Dump();
        return base.Equals(obj);
    }
}

private class Baz {
    public override bool Equals(object obj) { 
        "Baz.Equals() called".Dump();
        return RuntimeHelpers.Equals( this, obj );
    }
}

private class Qux {
    public override bool Equals(object obj) { 
        "Qux.Equals() called".Dump();
        return true;
    }
}

下面的打印输出:

prints the output below:

Bar.Equals()名为

Bar.Equals() called

Baz.Equals()名为

Baz.Equals() called

Qux.Equals()名为

Qux.Equals() called

所以我cribbed一点从<一个href="http://stackoverflow.com/questions/8870442/how-is-math-pow-implemented-in-net-framework/8870593#8870593">an回答汉斯帕桑特了约 Math.Pow() ...

So I cribbed a little from an answer Hans Passant gave about Math.Pow()...

这是从\ CLR的\ src \虚拟机\ ecall.cpp中的 SSCLI2.0

This is the relevant code from \clr\src\vm\ecall.cpp in SSCLI2.0

FCFuncStart(gObjectFuncs)
    FCIntrinsic("GetType", ObjectNative::GetClass, CORINFO_INTRINSIC_Object_GetType)
    FCFuncElement("InternalGetHashCode", ObjectNative::GetHashCode)
    FCFuncElement("InternalEquals", ObjectNative::Equals)
    FCFuncElement("MemberwiseClone", ObjectNative::Clone)
FCFuncEnd()

这是在code在功能\ CLR的\ src \虚拟机\ comobject.cpp其所映射的:

This is the code for the function in \clr\src\vm\comobject.cpp to which it is mapped:

FCIMPL2(FC_BOOL_RET, ObjectNative::Equals, Object *pThisRef, Object *pCompareRef)
{
    CONTRACTL
    {
        THROWS;
        DISABLED(GC_NOTRIGGER);
        INJECT_FAULT(FCThrow(kOutOfMemoryException););
        MODE_COOPERATIVE;
        SO_TOLERANT;          
    }
    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->IsValueClass())
        FC_RETURN_BOOL(FALSE);

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

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

    FC_GC_POLL_RET();

    FC_RETURN_BOOL(ret);
}
FCIMPLEND

我看到的参考比较,null检查,值类型排除,类型匹配检查,并逐位相等比较。我看不出的Object.Equals(对象)是不断调用。我认为, RuntimeHelpers.Equals的文件(对象,对象)简直是不正确。

I see the reference comparison, null checks, value type exclusion, type match check, and a bitwise equality comparison. I don't see how Object.Equals(Object) is ever called. I believe that the documentation for RuntimeHelpers.Equals(object,object) is simply incorrect.

这篇关于Object等 - 什么纯粹的对象或引用类型不重写等于基本逻辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆