C#中Equality和Identity浅析

 更新时间:2014年12月08日 11:32:30   投稿:junjie  
这篇文章主要介绍了C#中Equality和Identity浅析,本文先是讲解了Equality和Identity的定义,同时讲解了判断两个对象等价性的4种方法,需要的朋友可以参考下

CLR提供了可以区分类型的Equality 和Identity能力。

Equality:如果两个对象是相同的类型,并且它们各自带有相同和等值的属性。(They are instances of the same type and if each of the fields in one object matches the values of the fields in the other object)

Equality必须满足三个必要条件:reflexive, symmetrics, and transitive
reflexive: 自身相等,及a==a 是永远成立的;
symmetrics: 对象性,及a==b成立那么b==a 也成立;
transitive: 传递性,及a==b, b==c成立那么a==c 也成立。

Identity:两个对象必须相等(意味着他们共享同一块内存区域)(The two objects have the same values. – Two objects are identical if they share an address in memory)

CLR提供了至少四种方法来判断两个对象的等价性:

1.Public static bool ReferenceEquals(object left, object right);
2.Public static bool Equals(object left, object right);
3.Public virtual bool Equals(object right);
4.Public static bool operator==(MyClass left, MyClass right);

ReferenceEquals方法总是用来判断两个对象的Identity的,不管是针对值类型还是引用类型。所以针对值类型,调用该方法总是会返回false,因为值类型作为这个方法的参数时会进行装箱操作。

静态的Equals方法提供了判断两个对象的Equality能力,在其实现的内部,调用了上述第三个虚拟的Equals方法。和ReferenceEquals一样,它们已经具备从底层判断两个对象的能力,我们从来不会覆写这两个方法。

实例Equals方法也是用来区分两个对象的Equality的。

对于引用类型的对象,它和ReferenceEquals方法几乎是一样的。(因为判断两个引用类型是否的Equality往往从Identity上就可以区分)

而值类型的对象,我们不仅要判断他们具有相同的对象类型,还要判断他们的值相等。值类型从System.ValueType继承而来,ValueType已经重写了Object.Equals()方法,本来已经可以用来满足这些要求的。但是ValueType.Equals()方法不是很有效,因为它必须要通过反射,在不知道具体的派生类型中,完成对它们所含有成员变量的值的比较。因此,建议在我们实现一个值类型的数据结构时,同时重写ValueType.Equals()方法。

然而我们再回头看看引用类型,有时两个引用类型的对象往往被用来进行类似值类型的比较,比如:String类型,它虽然是引用类型,但它也重写了Equals方法,因为我们拿它来判断两个string是否相同(Equality),实际是希望判断它们是否具有相同的内容,这是一个value semantics。因此,我们建议在考虑实现一个用作值语义环境下的引用类型时候,也重写基类的Object.Equals()方法。

注:请参考MDSN或其它相关文档,如何实现Equals方法的重写。

上面的图示给了很好的例子来区分Equals和ReferenceEquals方法,被用来做Equility和Identity判断的区别。

\== 运算符是可由类重载的运算符,它也是用来判断恒等的。 对于未重载= =的引用类型,会比较两个引用类型是否引用同一个对象。这跟引用类型的Equals()方法是一样的。

对于未重载= =的值类型,该运算符会比较这两个值是否"按位"相等,即是否这两个值中的每个字段都相等。和Equals方法一样,推荐在自定义值类型中,也要重载= =运算符,因为也存在反射在效率上的影响。

\== 运算符和Equals方法的区别在于多态表现上。Equals方法是重写,而= =运算符是被重载。这意味着除非编译器知道调用具体的重载版本,否则它只是调用未重载的= =版本。

相关文章

  • 详解C#读取Appconfig中自定义的节点

    详解C#读取Appconfig中自定义的节点

    我们往往需要在App.config中自定义一些节来满足实际需要,而不依赖于App.config的appSettings,下面通过一个简单的实例来说明自定义配置节点的设置与读取
    2015-06-06
  • C#使用WebSocket与网页实时通信的实现示例

    C#使用WebSocket与网页实时通信的实现示例

    本文主要介绍了C#使用WebSocket与网页实时通信的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • C#中析构函数、Dispose、Close方法的区别

    C#中析构函数、Dispose、Close方法的区别

    本文详细对比了C#中析构函数、Dispose和Close方法的区别,三者都是释放资源,本文介绍了他们各自的使用方法和使用场景,希望对大家有所帮助。
    2016-04-04
  • ref与out之间的区别深入解析

    ref与out之间的区别深入解析

    以下是对c#中ref与out之间的区别进行了详细分析介绍,需要的朋友可以过来参考下
    2013-09-09
  • C# WindowsForm程序同时启动多个窗口类

    C# WindowsForm程序同时启动多个窗口类

    这篇文章主要为大家详细介绍了C# WindowsForm程序同时启动多个窗口类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • C#9.0主要特性的一些想法

    C#9.0主要特性的一些想法

    这篇文章主要给大家介绍了关于C#9.0主要特性的一些想法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • C#数据结构与算法揭秘三 链表

    C#数据结构与算法揭秘三 链表

    这节我们讨论链表的基本操作,并且画图以证明,下届中我们将讨论双向链表,环形链表 应用举例
    2012-11-11
  • C#表达式中的动态查询详解【译】

    C#表达式中的动态查询详解【译】

    这篇文章主要给大家介绍了关于C#表达式中动态查询的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Unity3D UI Text得分数字增加的实例代码

    Unity3D UI Text得分数字增加的实例代码

    这篇文章主要介绍了Unity3D UI Text得分数字增加方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • CPF 使用C#的Native AOT 发布程序的详细过程

    CPF 使用C#的Native AOT 发布程序的详细过程

    这篇文章主要介绍了CPF 使用C#的Native AOT 发布程序,本文给大家介绍的非常详细,对大家的学习或工作具体一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03

最新评论