ReferenceEquals()的合法用途

7
在遵循声明式编程风格的.NET程序中,ReferenceEquals()有哪些合法使用?

2
一个合法的用途是当你想回答这个问题:“这两个引用是否指向同一个对象?” - phoog
1
你所说的声明式风格是什么意思,它与引用相等性有什么关系? - CodesInChaos
1
@GregC 知道, 显然也知道,但是阅读代码的 每个程序员 都知道吗,而不必去查找吗? - phoog
1
对于那些不打算重写Equals的类,非虚拟的ReferenceEquals方法比使用带有关联虚拟调度的Equals更快。速度优势足以证明在Object.Equals(Object,Object)的位置使用它是合理的。更有趣的问题是,当Equals(X,Y)为真但ReferenceEquals(X,Y)为假时是否应该认为违反了封装性。在我看来,从实质上讲,应该这样认为。 - supercat
1
@GregC:在C#中,让==运算符调用Object.Equals而不是执行与ReferenceEquals等效的引用比较,会导致很多代码运行得更慢。从概念上讲,给定string s1="0"; string s2=0.ToString(); string s3=s1;",我们无法确定s3是从s2还是从s1复制过来的,但确保所有包含相同字符的字符串真正无法区分将会非常昂贵,并且并没有太多好处。 - supercat
显示剩余6条评论
3个回答

12

不确定你所说的“按照声明式风格编写”的含义是什么,但通常在重载==运算符时使用ReferenceEquals。来自http://msdn.microsoft.com/en-us/library/ms173147.aspx

public static bool operator ==(ThreeDPoint a, ThreeDPoint b)
{
    // If both are null, or both are same instance, return true.
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    // If one is null, but not both, return false.
    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    // Return true if the fields match:
    return a.x == b.x && a.y == b.y && a.z == b.z;
}

重要提示请看下面的注释

注:在重载运算符==时常见的一个错误是使用(a == b)、(a == null)或(b == null)来检查引用相等性。这会导致调用重载的operator==,从而导致无限循环。使用ReferenceEquals方法,或将类型强制转换为Object类型,以避免循环。


1
@GregC 这里的检查是必要的,否则 null==null 的情况会出问题。另外请注意,这些 null 检查本身使用引用相等性。它们只是使用对象转换而不是 ReferenceEquals。(ReferenceEquals(a,b) 等同于 (object)a==(object)b) - CodesInChaos
@GregC 不能保证完全相同,但从上下文来看应该是一样的。如果它表现不同,很可能是深度相等部分的一个错误。 - Servy
如果没有检查ReferenceEquals并且a和b都为null,那么这将返回false。由于有了它,它将返回true。 - Chris Shain
1
将空值检查改为异或操作可能更合理。这样做在技术上符合要求,并消除了对先前检查的不确定依赖。它对实际性能没有影响,只会提高代码的可读性和可维护性。 - Servy

11
在编写遵循声明式风格的.NET程序中,ReferenceEquals()有哪些合法使用方式?
无论程序以何种“风格”编写,只有一种合法使用ReferenceEquals():用于比较两个引用是否具有引用相等性。
如果您使用ReferenceEquals()来执行除比较两个引用是否具有引用相等性之外的操作,则可能存在错误。

2
有点太重复了,不太符合我的口味。 - CodesInChaos
4
@CodeInChaos说的话有点啰嗦,但意思是:虽然显而易见,但考虑到使用GetHashCode来平衡哈希表以外的其他目的的人数,或者在需要判断字符串相等性时使用字符串排序的人数,或者在想要判断是否存在元素时使用Count()的人数。 - Eric Lippert
8
如果您想得到更具体的答案,那就提出更具体的问题。 - Eric Lippert
1
@GregC:我完全同意你的观点。有多种不同的方法可以比较两个东西是否相等,这真的很令人困惑,而当你把排序也考虑进去时,情况会变得更糟。 - Eric Lippert
2
编译器生成一个引用比较。 - Eric Lippert
显示剩余4条评论

1

如果相关对象的设计和/或用法是这样的,即任何对象的实例都不会有多个“相等”,那么它将是正确的,并且比比较一些实例变量要快。

或者,如另一个答案中所发布的那样,您可以首先将其检查为“易于退出”,仅在它们不同的情况下执行深度相等检查。 这种用法只是性能提高。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接