C#比較对象的相等性
对于相等的机制全部不同,这取决于比較的是引用类型还是值类型。以下分别介绍引用类型和值类型的相等性。
1.比較引用类型的相等性
System.Object定义了三种不同的方法,来比較对象的相等性:ReferenceEquals()和两个版本号的Equals()。再加上比較运算符(==)。实际上有4种进行比較相等的方式。
1.1 ReferenceEquals()方法
命名控件: System
程序集:mscorlib.dll
语法:public static bool ReferenceEquals(Object objA, Object objB)
能够看出ReferenceEquals()是一个静态方法,确定指定的Object实例是否是同样的实例。作为静态方法。所以不能重写。
1.1.1 使用ReferenceEquals()方法比較值类型
int int1 = 3;
bool B1 = Object.ReferenceEquals(int1, int1);//B1为false
因为objA和objB是值类型,首先进行装箱。然后传递给ReferenceEquals()方法。这意味着,即使objA和objB表示值类型的同一个实例,ReferenceEquals()方法也返回false。
1.1.2 使用ReferenceEquals()方法比較字符串
String s1 = "String1";
String s2 = "String1";
bool B2 = Object.ReferenceEquals(s1, s2);//true
String suffix = "A";
String s3 = "String" + suffix;
String s4 = "String" + suffix;
bool B3 = Object.ReferenceEquals(s3, s4);//false
当比較字符串时 假设 objA 和 objB 是字符串,假设该字符串会暂留,ReferenceEquals 方法返回 true。 它不运行值相等測试。
在以下的演示样例中。由于它们是一个暂存的字符串的两个实例,s1 和 s2 相等。 可是,s3 和 s4 不相等,由于虽然它们是具有同样的字符串值。字符串不会暂留。
1.1.3 使用ReferenceEquals()比較两个对象
object o = null;
object p = null;
object q = new Object();
bool B4 = Object.ReferenceEquals(o, p);//true
p = q;
bool B5 = Object.ReferenceEquals(p, q);//true
bool B6 = Object.ReferenceEquals(o, p);//false
1.2 Equals()方法
1.2.1 虚拟的Equals()方法
命名空间: System
程序集:mscorlib(在mscorlib.dll中)
语法:public virtual bool Equals(Object obj)
Equals()虚拟版本号的System.Object实现代码也比較引用。
但由于这种方法是虚拟的。所以能够在自己的类中重写它。按值来比較对象。
特别是假设希望类的实例用作字典中的键,就须要重写这种方法,以比較值。否则。依据重写Object.GetHashCode()的方式。包括对象的字典类要么不工作,要么工作的效率很低。在重写Equals()方法时要注意,重写的代码不会抛出异常。这是由于假设抛出异常。字典类就会出问题,一些在内部调用这种方法的.NET基类也可能出问题。
Equals 是一个虚方法。同意不论什么类重写事实上现。
表示某个值(本质上能够是不论什么值类型)或一组值(如复数类)的不论什么类都应该重写 Equals。假设类型要实现 IComparable,则它应该重写 Equals。
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。
Equals 的新实现不应该引发异常。建议重写 Equals 的不论什么类同一时候也重写 System.Object.GetHashCode。
除了实现 Equals(对象)外。还建议全部的类为自己的类型实现 Equals(类型)以增强性能。
比如:
class TwoDPoint : System.Object
{
public readonly int x, y;
public TwoDPoint(int x, int y) //constructor
{
this.x = x;
this.y = y;
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public bool Equals(TwoDPoint p)
{
// If parameter is null return false:
if ((object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public override int GetHashCode()
{
return x ^ y;
}
}
1.2.2 静态的Equals()方法
命名空间: System
程序集:mscorlib(在mscorlib.dll中)
语法:public static bool Equals(Object objA, Object objB)
Dog m1 = new Dog("Alaskan Malamute");
Dog m2 = new Dog("Alaskan Malamute");
Dog g1 = new Dog("Great Pyrenees");
Dog g2 = g1;
Dog d1 = new Dog("Dalmation");
Dog n1 = null;
Dog n2 = null;
Console.WriteLine("null = null: {0}", Object.Equals(n1, n2));//true
Console.WriteLine("null Reference Equals null: {0}\n", Object.ReferenceEquals(n1, n2));//true
Console.WriteLine("{0} = {1}: {2}", g1, g2, Object.Equals(g1, g2));//true
Console.WriteLine("{0} Reference Equals {1}: {2}\n", g1, g2, Object.ReferenceEquals(g1, g2));//true
Console.WriteLine("{0} = {1}: {2}", m1, m2, Object.Equals(m1, m2));//true
Console.WriteLine("{0} Reference Equals {1}: {2}\n", m1, m2, Object.ReferenceEquals(m1, m2));//false
Console.WriteLine("{0} = {1}: {2}", m1, d1, Object.Equals(m1, d1)); //false Console.WriteLine("{0} Reference Equals {1}: {2}", m1, d1, Object.ReferenceEquals(m1, d1)); //false
静态 Equals(Object, Object) 方法指示两个对象。objA 和 objB,是否相等
它确定两个对象是否表示同一对象引用。 假设成功,该方法返回 true. 这測试与调用 ReferenceEquals 方法等效。 另外。假设 objA 和 objB 都为 null,则方法返回 true。
它确定 objA 或 objB 是否 null。 假设是这样。则返回 false。
假设两个对象不表示同一对象引用,且均不为 null,它调用 objA。
Equals(objB) 而且返回结果。
这意味着。假设 objA 重写 Object.Equals(Object) 方法,该重写调用。
1.3 比較运算符(==)
对于引用类型,== 默认的行为与ReferenceEquals的行为同样,仅有两个对象指向同一个Reference的时候才返回true。可是.NET Framework中的类非常多对==进行了重载,比如String类的==与Equals的行为同样。推断两个字符串的内容是否相等。所以在应用中。对于 系统定义的引用类型建议不要使用==操作符,以免程序出现与预期不同的执行结果。
重载的运算符 == 实现不应引发异常。重载运算符 == 的不论什么类型还应重载运算符 !=。
比如:
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;
}
public static bool operator !=(ThreeDPoint a, ThreeDPoint b)
{
return !(a == b);
}
2.比較值类型的相等性
在比較值类型的相等时,採用与引用类型同样的规则:ReferenceEquals()用于比較引用,Equals()用于比較值,比較运算发能够看做是一个中间项。但最大的差别是值类型须要装箱。才干把他们转换为引用。
ReferenceEquals()在应用于值类型时。总是返回false。
由于调用这种方法,须要装箱。
C#比較对象的相等性的更多相关文章
- Java中测试对象的等价性
Java中用于测试对象的等价性有三个操作符:== , != 和 Equals() 对于基本类型即int,boolean, byte 等等来说,==和 != 比较的是 基本类型的内容,这和c.c++是一 ...
- JavaScript大杂烩3 - 理解JavaScript对象的封装性
JavaScript是面向对象的 JavaScript是一种基于对象的语言,你遇到的所有东西,包括字符串,数字,数组,函数等等,都是对象. 面向过程还是面向对象? JavaScript同时兼有的面向过 ...
- C#编程(三十九)----------比较对象的相等性
比较对象的相等性 需要理解对象相等的机制对逻辑表达式的编程很重要,另外,对实现运算符重载和类型强制转换也很重要. 对象相等的机制有所不同,这取决于比较的是引用类型还是值类型. 比较引用类型的相等性 S ...
- 一起学习《C#高级编程》2--比较对象的相等性
今后争取每两天能更新一次.平日的诱惑太多,双休只顾玩了,进度有点慢. 接上一讲的,类型的安全性,留下了点小尾巴——比较对象的相等性. C#有四种比较相等的方式:除了“==”运算符外,System.Ob ...
- Java连载37-面向对象的封装性
一.IDE上继续新建工程 1.在src目录下新建软件包:package机制后面再讲,目前先用着 2.给package命名一个名称:com.bjpowernode.java_learning 3.软件包 ...
- 跟着百度学PHP[4]-OOP面对对象编程-2-属性和方法
简单的说 变量就是成员属性函数就是成员方法(方法有三:构造方法[即为__construct].成员方法.析构方法[__destruct]) 成员方法和成员属性都是可以加修饰词.比如封装性的方法或者属性 ...
- c# 面相对象2-之封装性
一.封装特性: 这是一种隐藏的特性.可以用一个公式来展示类的封装特性: 封装的类=数据 + 对此数据进行的操作(即算法) 通俗的说,封装就是:包起外界不必要知道的东西,只向外界展露可供展示的东西. ...
- c# 面相对象4-多态性
一.定义: 多态是面向对象程序设计的又一个特性.在面向过程的程序设计中,主要工作是编写一个个的过程或函数,这些过程和函数不能重名.例如在一个应用中,需要对数值型数据进行排序,还需要对字符型数据进行排序 ...
- 24.编写一个Car类,具有String类型的属性品牌,具有功能drive; 定义其子类Aodi和Benchi,具有属性:价格、型号;具有功能:变速; 定义主类E,在其main方法中分别创建Aodi和Benchi的对象并测试对象的特 性。
package zhongqiuzuoye; public class Car { String brand; public void drive() {} } package zhongqiuzuo ...
随机推荐
- [luoguP2657] [SCOI2009]windy数(数位DP)
传送门 f[i][j]表示位数为i,第i位为j的windy数的个数 先预处理出f数组. 求的时候先算没有前导0的答案,再算位数和给定的数相同的答案. #include <cmath> #i ...
- 【CCF】 Markdown 模拟
#include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...
- python3的cookielib
http://stackoverflow.com/questions/8405096/python-3-2-cookielib
- C++ qsort() 函数调用时实参与形参不兼容的问题解决
<剑指OFFER>刷题笔记 —— 扑克牌顺子 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自 ...
- HTML 改变文字方向
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- iOS笔记-(缓存机制的理解与实现)
(1)运行中的现象: 在iOS开发中,会遇到:同一NSURL被多次请求,会造成用户的流量浪费,程序的响应速度不够快.比如说,从服务器上请求一张图片,请求100次,下载的结果都是一样的. (2)解决方法 ...
- ext2/3/4的inode结构说明
系统环境:Ubuntu15.10/ext4 今天在复习<鸟哥的私房菜-基础学习篇>,看到inode大小为128bytes,想看下这128字节里面到底是什么样的. 于是我查了下google, ...
- Android 读取手机联系人、拨号、发送短信及长按菜单的操作
本示例实现了读取手机联系人,拨号.发送短信及长按出现菜单选项的操作↓ 1.Andrid项目结构图↓主要操作图中红色方框内的文件. 2.首先布局代码如下↓ a, main.xml 程序运行的主界面,主要 ...
- Linux中查看某个软件的安装路径
Linux中查看某个软件的安装路径(地址)有时显得非常重要.比如某个文件的快速启动项被删除,或者你要建立快速启动项,或者想删除.添加安装文件等等,很多地方都要用到查案文件安装路径的命令. 这里给大家介 ...
- Codeforces 746G(构造)
G. ...