对象相等和一致性
来源:互联网 发布:大数据专业建设方案 编辑:程序博客网 时间:2024/05/21 09:34
在对象比较中,对象一致和对象相等:
简单的讲:相等性(quality)就是两个对象,它们的值相等。同一性(identity)就是指引用的是否为同一个对象。
下面是我的读书笔记:
C# 中有两种不同的相等:引用相等和值相等。值相等是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。引用相等意味着要比较的不是两个对象,而是两个对象引用,这两个对象引用所引用的是同一个对象。我们这里把值相等叫做对象的“相等性(equality)”,把引用相等叫做对象的同一性(identity)。
我们都知道在System.Object类型中提供了一个名为Equals的虚方法,它的作用是在两个对象相等的情况下返回true,不相等时返回false。等等,这里的说的“相等”是哪个?是“相等性(equality)”还是“同一性(identity)”。好吧,来看一下代码吧,System的Object方法是像下面这样实现的:
public class Object
{
public virtual Boolean Equals(Object obj)
{
// 如果两个引用指向的是同一个对象,那么它们肯定相等
if (this == obj) return true;
// 假定对象不相等
return false;
}
}
表明上看它好像是实现的很合理:假如this和Obj引用同一对象,自然就是true了,因为Equals知道一个对象肯定等于它自身。然而,如果this和Obj引用不同的对象哪?,Equals就不能肯定对象是否包含相同的值,所以总结一句话就是:Object的Equals方法实现的只是“同一性(identity)”,而不是“相等性(equality)”。
多么的令人遗憾啊~!Object的Equals的默认实现并不合理,既然不合理我们就来重写它吧,先来看看如何在内部正确实现一个Equals方法(我把它概括为四个字——空、型、值、基):
如果obj参数为null,就返回false;
如果this和obj参数引用不同的类型对象,返回false;
针对类型定义的每个实例字段,将this对象的值和obj对象的值进行对比,任何字段不相等,就返回false;
调用基类的Equals方法,以便比较它定义的任何字段。如果基类的Equals方法返回false,就返回false;否则返回true;
再来看一下Object的Equals方法的实现代码:
public class Object
{
public virtual Boolean Equals(Object obj)
{
if (obj == null) return false;
if (this.GetType() != obj.GetType()) return false;
// 如果对象属于相同的类型,那么在它们的多有字段都匹配的前提下返回true
// 由于System.Object没有定义任何字段,所以字段是匹配的
return true;
}
}
其实,这里要说一下,Microsoft并没有这样去实现他的代码,而是要比这个复杂的多的多。
那么Equals方法可以在子类中重写,那么就不可以用Equals方法来测试同一性(identity)了。怎么办啊?Microsoft在Object中提供了一个静态方法ReferenceEquals,其原型如下:
public class Object
{
public static Boolean ReferenceEquals(Object objA, object objB)
{
return (objA == objB);
}
}
注意了啊,如果想要检查同一性(identity),那么务必调用ReferenceEquals,而不应该使用C#的==操作符(除非事先把它们转化为Object类型),原因是其中某个操作数的类型可能重载了==操作符,为其赋予了其它语义。
另外,System.ValueType重写了Object的Equals方法。并进行了正确的实现来执行相等性(equality)检查,而不是同一性(identity)检查。在内部,ValueType的Equals方法是像这样实现的:
如果obj参数为null,返回false;
如果this和obj引用的不同类型的对象,返回false;
针对类型定义的每个实例字段,都将this对象的值和obj对象中的值进行比较。如果有字段不相等,就返回false;
返回true;ValueType的Equals的方法不会调用Object的Equals方法。
顺便说一下,ValueType的Equals方法是通过反射技术来完成的。由于CLR反射机制较慢,所以在定义自己的值类型时,应该重写Equals方法,并提供自己的实现,以便提高性能。当然在自己的实现中不要调用base.Equals。
要重写Equals,必须遵循一下几点特性:
x.Equals(x) 返回 true。 (自反性)
x.Equals(y) 与 y.Equals(x) 返回相同的值。 (对称性)
如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。 (传递性)
只要不修改 x 和 y 所引用的对象,x.Equals(y) 的后续调用就返回相同的值。 (一致性)
x.Equals(null) 返回 false。
另一人回答:对象们都住在不同的房间里,每个房间只能住一个对象.对象们都被锁在房间里,永远没有办法搬家(至少从我们讨论的角度来说,这个说法是正确的).所以如果你知道了一个对象的房间号,就能找到对应的对象.
现在假如我们有两张名片,上面如果写着相同的房间号,我们就可以断定,这两张名片是同一个对象分发出来的,这就是同一性,也就是你所说的一致.
假如1号房里住着一个值为1的整数对象, 2号房里住着另一个值为2的整数对象,3号房里住着另另一个值为1的整数对象.我们又有它们各自的一张名片, 那么,第一个名片和第三个对应的对象的值是相等的,但是它们不是同一个对象,用你的词来说,也就是说它们"相等",但不"一致".
如果上面说得太清楚了,那么这里让你再困扰一会吧,哈哈:
这里的名片就是引用(i, count之类的变量/字段等的名称);
房间所在的大楼就是内存,房间号就是内存地址.
对象就是内存里保存的数据.
- 对象相等和一致性
- Java 中的相等性和一致性
- java类对象自然顺序的相等一致性
- "一致性相等"的陷阱
- Java常见问题之引用相等性和对象相等性
- 面向对象编程两个重要的相等概念:值相等和引用相等
- 从误用TreeSet到思考Java有序集合对相等和顺序比较一致性的要求
- java :两个对象相等equals和==的区别
- hashcode()和equals()及HashSet判断对象相等
- hashcode()和equals()及HashSet判断对象相等
- 集合Set判断对象是否相等的equals和hashCode
- java基础之Integer和Long对象相等比较
- java基础之Integer和Long对象相等比较 .
- java基础之Integer和Long对象相等比较 .
- 判断两个对象相等 和重写equals、 hashcode
- python对象的相等
- 比较两个对象相等
- js 比较对象相等
- 随笔
- vc IIS在非默认网站下创建虚拟目录
- 计较,是贫穷的开始
- SQL SplitString function
- 显示单位px和dip以及sp的区别
- 对象相等和一致性
- java.lang.OutOfMemoryError: Java heap space 解决方法
- MyEclipse6.5安装SVN插件的三种方法
- 运算符重载
- 博客还要开通
- [绝对原创]关于VC6.0中,无法添加书签(ADD bookmarks)的解决办法
- 利用VB开发DLL的方法
- 成功激励格言精选
- SharePoint基础之五- SharePoint基础架构中涉及的IIS初步