System.Object 类中的三个比较方法浅析
2010-06-24 01:33
211 查看
在System.Object类中有三个被设计用来进行对象比较的方法:
第一个是virtual 的,后两个是 static 的。ReferenceEquals() 实现了类型的引用比较,对该函数来讲,只有应用在引用类型上时才会有意义,比较两个值类型的引用将永远返回 false ,
无论它们的值是否相等。甚至下面的代码:
int i = 0;
Console.WriteLine(object.ReferenceEquals(i, i));
输出结果也是 false . 原因是:i 是值类型的int .在传入时被自动装箱为object型变量,并且装了两次,那就是两个不同的对象啦,因此引用不相等(原因是我猜测的,存疑!)
另一个静态的 Equals() 方法的功能根据不同的类型而有所不同。它的内部判断实际分了两步:首先检查两个对象是否恒等(对于值类型来说,就是检查值内容是否相等;对于引用类型来说,就是检查引用是否相等)。然后调用其中一个参数对象的实例的Equals方法来判断两个对象是否恒等。
利用反射可以看到 静态方法 Equals() 的代码:
public static bool Equals(object objA,object objB)
{
return ((objA == objB || (((objA != null && objB != null && objA.Equals(objB)));
}
注意这里面只有一行代码,却是别有意味。它通过一个 || 运算符,把两种情况,值类型,跟引用类型,都包含了进去。一一分析:
如果objA , objB 皆为 值类型,则在 objA == objB 这一步骤无论如何都要得到一个false ,理由同前,因为它们要被装箱。实验如下:
int ia = 5;
int ib = 5;
object oa = ia; //这儿手动装下箱。
object ob = ib;
Console.WriteLine(oa == ob); // 结果是 false!!!
这时候后备的半句就用上了,
首先用 objA != null && objB != null 确保两个参数皆不为null ,然后调用了值类型本身的Equals 方法,这时候要明白,所有的值类型都继承自 System.ValueType 类,而ValueType 类复写了
方法,此时的Equals(Object obj)就可以进行值类型的恒等判断了,比较的是里面存放的内容,而非引用,这时候就能得到正确的结果了。验证如下:
int ia = 5;
int ib = 5;
object oa = ia;
object ob = ib;
Console.WriteLine(oa == ob); // 结果是 false!!!
Console.WriteLine(oa.Equals(ob)); // 结果是 true !!!!!
前面我们假设的是两个值类型的情况,可以正常满足判断功能。当两个参数皆为引用类型的时候,objA == objB 这前半个条件已经够用了。当两个参数一个为值类型一个为引用类型,那就显然不用说,也会得到false 啦。。。
最后还有一个virtual 的 Equals(object obj) 方法,当我们需要构建自定义的比较时,就需要重写该方法,它的默认实现是大多情况下并不实用的引用比较,当然System.ValueType已经复写了该方法。所以系统定义的那些值类型可以放心使用,它们会正常比较值的内容的。
下面部分转自:在路上
重写Equals方法分为以下三种情况:
1.引用类型的基类没有重写Equals
2.引用类型的基类重写了Equals
3.值类型重写了Equals
通常写法是:
对象是否为空,为空返回false
对象类型是否相同,不同返回false
类型转换后进行引用与值的比较如下:
Object.Equals(v1,v2) ,不同返回false
v1.Equals(v2),不同返回false
对于基类,if(!base.Equals(v2)) return false;
值类型可以自己实现强类型的Equals,避免拆箱与装箱操作.注意System.ValueType.Equals()利用了反射实现,效率不高.
注意:Object.ReferenceEquals();
重写Equals必须重写GetHashCode()
public virtual bool Equals(Object obj);
public static bool Equals(Object objA,Object objB);
public static bool ReferenceEquals(Object objA,Object objB);
第一个是virtual 的,后两个是 static 的。ReferenceEquals() 实现了类型的引用比较,对该函数来讲,只有应用在引用类型上时才会有意义,比较两个值类型的引用将永远返回 false ,
无论它们的值是否相等。甚至下面的代码:
int i = 0;
Console.WriteLine(object.ReferenceEquals(i, i));
输出结果也是 false . 原因是:i 是值类型的int .在传入时被自动装箱为object型变量,并且装了两次,那就是两个不同的对象啦,因此引用不相等(原因是我猜测的,存疑!)
另一个静态的 Equals() 方法的功能根据不同的类型而有所不同。它的内部判断实际分了两步:首先检查两个对象是否恒等(对于值类型来说,就是检查值内容是否相等;对于引用类型来说,就是检查引用是否相等)。然后调用其中一个参数对象的实例的Equals方法来判断两个对象是否恒等。
利用反射可以看到 静态方法 Equals() 的代码:
public static bool Equals(object objA,object objB)
{
return ((objA == objB || (((objA != null && objB != null && objA.Equals(objB)));
}
注意这里面只有一行代码,却是别有意味。它通过一个 || 运算符,把两种情况,值类型,跟引用类型,都包含了进去。一一分析:
如果objA , objB 皆为 值类型,则在 objA == objB 这一步骤无论如何都要得到一个false ,理由同前,因为它们要被装箱。实验如下:
int ia = 5;
int ib = 5;
object oa = ia; //这儿手动装下箱。
object ob = ib;
Console.WriteLine(oa == ob); // 结果是 false!!!
这时候后备的半句就用上了,
首先用 objA != null && objB != null 确保两个参数皆不为null ,然后调用了值类型本身的Equals 方法,这时候要明白,所有的值类型都继承自 System.ValueType 类,而ValueType 类复写了
public virtual bool Equals(Object obj);
方法,此时的Equals(Object obj)就可以进行值类型的恒等判断了,比较的是里面存放的内容,而非引用,这时候就能得到正确的结果了。验证如下:
int ia = 5;
int ib = 5;
object oa = ia;
object ob = ib;
Console.WriteLine(oa == ob); // 结果是 false!!!
Console.WriteLine(oa.Equals(ob)); // 结果是 true !!!!!
前面我们假设的是两个值类型的情况,可以正常满足判断功能。当两个参数皆为引用类型的时候,objA == objB 这前半个条件已经够用了。当两个参数一个为值类型一个为引用类型,那就显然不用说,也会得到false 啦。。。
最后还有一个virtual 的 Equals(object obj) 方法,当我们需要构建自定义的比较时,就需要重写该方法,它的默认实现是大多情况下并不实用的引用比较,当然System.ValueType已经复写了该方法。所以系统定义的那些值类型可以放心使用,它们会正常比较值的内容的。
下面部分转自:在路上
重写Equals方法分为以下三种情况:
1.引用类型的基类没有重写Equals
2.引用类型的基类重写了Equals
3.值类型重写了Equals
通常写法是:
对象是否为空,为空返回false
对象类型是否相同,不同返回false
类型转换后进行引用与值的比较如下:
Object.Equals(v1,v2) ,不同返回false
v1.Equals(v2),不同返回false
对于基类,if(!base.Equals(v2)) return false;
值类型可以自己实现强类型的Equals,避免拆箱与装箱操作.注意System.ValueType.Equals()利用了反射实现,效率不高.
注意:Object.ReferenceEquals();
重写Equals必须重写GetHashCode()
相关文章推荐
- 在System.Object中定义的三个比较方法有何异同
- org.json.JsonObject的put和append方法比较
- Object的toString方法:Object的equals方法:System类的概念和构造:冒泡排序,自动装箱拆箱, Date类的常用方法:6 SimpleDateFormat的概述:
- 浅析jQuery删除节点的三个方法
- 三种禁用: FileSystemObject组件的方法
- VBA操作文件四大方法之三--FileSystemObject
- FSO有关的属性和方法(FileSystemObject)
- new ActiveXObject("Scripting.FileSystemObject") 未能创建对象的解决方法
- VBA遍历所有文件夹的两种方法(filesearch和FileSystemObject)
- 微软bug解决方法:System.ObjectDisposedException: 无法访问已释放的对象。对象名:“Icon”
- QT中获取选中的radioButton的两种方法(动态取得控件的objectName之后,对名字进行比较)
- List数据平均分放到三个List中的方法比较
- 浅析jQuery删除节点的三个方法
- .NET必知基础-System.Object中包含哪些方法,哪些是虚方法
- 三种禁用FileSystemObject组件的方法
- C# 方便的复制/比较物件内数据的方法(Object Copy / Compare)
- 在使用SMO时,检索IsSystemObject属性将导致性能急剧下降的解决方法
- 找不到方法:“Void System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior(Boolean)
- ArrayList的方法:remove(object o) 、remove(int index)、removeAll(Collection c)时间复杂度的比较
- FileSystemObject (FSO)对象方法总结及应用