为了账号安全,请及时绑定邮箱和手机立即绑定

C#.Equals()、. ReferenceEquals()和==运算符

C#.Equals()、. ReferenceEquals()和==运算符

C#
慕慕森 2019-10-17 13:58:24
我对这三个方面的理解是:.Equals()测试数据是否相等(缺少更好的描述)。.Equals()可以为同一对象的不同实例返回True,这是最常用的方法。.ReferenceEquals() 测试两个对象是否是同一实例,并且不能被覆盖。==与ReferenceEquals()默认情况下的相同,但是可以覆盖此设置。但是C#站指出:在对象类中,Equals和  ReferenceEquals方法在语义上是等效的,只不过该方法ReferenceEquals仅适用于对象实例。该  ReferenceEquals方法是静态的。现在我不明白。谁能对此有所启发?
查看完整描述

3 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

造成混淆的原因似乎是C#站的摘录中有一个错字,该错字应为:“ ...,但Equals仅适用于对象实例。ReferenceEquals方法是静态的。”


您对每个语义含义的差异大体上是正确的(尽管“同一对象的不同实例”似乎有些混乱,但它可能应该读为“同一类型的不同实例” ),并且可以对其进行覆盖。


如果我们将其放在一边,让我们处理您的问题的最后一部分,即它们如何与普通System.Object实例和System.Object引用一起使用(我们都需要规避的非多态性质==)。在此,所有这三个操作将等效地工作,但有一个警告:Equals无法在上调用null。


Equals是采用一个参数(可以是null)的实例方法。由于它是一个实例方法(必须在实际对象上调用),因此不能在null-reference 上调用。


ReferenceEquals是一个采用两个参数的静态方法,其中两个参数都可以是null。由于它是静态的(不与对象实例相关联),因此NullReferenceException在任何情况下都不会抛出。


==是运算符,在这种情况下(object)的行为与相同ReferenceEquals。它也不会抛出NullReferenceException。


为了显示:


object o1 = null;

object o2 = new object();


//Technically, these should read object.ReferenceEquals for clarity, but this is redundant.

ReferenceEquals(o1, o1); //true

ReferenceEquals(o1, o2); //false

ReferenceEquals(o2, o1); //false

ReferenceEquals(o2, o2); //true


o1.Equals(o1); //NullReferenceException

o1.Equals(o2); //NullReferenceException

o2.Equals(o1); //false

o2.Equals(o2); //true


查看完整回答
反对 回复 2019-10-17
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

看一下有关该主题的这篇MSDN文章。


我认为有关的要点是:


要检查引用是否相等,请使用ReferenceEquals。要检查值是否相等,请使用“等于”或“等于”。


默认情况下,operator ==通过确定两个引用是否指示同一对象来测试引用是否相等,因此引用类型不需要实现operator ==即可获得此功能。当类型是不可变的,这意味着实例中包含的数据无法更改时,重载运算符==以比较值相等而不是引用相等是很有用的,因为作为不可变对象,只要它们具有相同的值。


希望这可以帮助!


查看完整回答
反对 回复 2019-10-17
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

想要加上与“ null”比较的5美分。

  1. ReferenceEquals(对象,对象)与“(object)arg1 == arg2”相同(因此,在使用值类型的情况下,您将获得装箱并且需要时间)。但是这种方法是在几种情况下检查参数是否为null的唯一100%安全的方法,例如

    • a)在通过调用其成员之前。算子

    • b)检查AS运算符的结果。

  2. ==和Equals()。为什么我要说ReferenceEquals使用null检查是100%安全的?想象一下,您在核心跨项目库中编写了通用扩展,并说您将通用参数类型限制为某些域类型。这种类型可以引入“ ==”运算符-现在或以后(相信我,我已经看到很多,这种运算符可以具有非常“奇怪的”逻辑,尤其是在涉及域或持久性对象时)。您尝试检查参数是否为null,然后对其调用成员操作。惊喜,您可以在此处使用NullRef。因为==运算符几乎与Equals()相同-非常自定义且非常不可预测。但是有一个区别,应该加以考虑-如果您不将通用参数限制为某些自定义类型(==仅在您的类型为“类”时才可以使用),==运算符与object相同。ReferenceEquals(..)。等于实现始终是从最终类型使用的,因为它是虚拟的。

因此,我的建议是,当您编写自己的类型或从知名类型派生时,可以使用==检查null。否则,请使用object.ReferenceEquals(arg,null)。


查看完整回答
反对 回复 2019-10-17
  • 3 回答
  • 0 关注
  • 480 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信