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。

由于调用这种方法,须要装箱。

时间: 2024-08-27 07:25:21

C#比較对象的相等性的相关文章

细说对象的相等性

1 从Object.Equals方法说起 使用Object.Equals方法能够确定两个Object实例是否相等. Object.Equals方法具有下面重载形式: (1)Object.Equals (Object)  该方法能够确定指定的Object是否等于当前的Object.相等时返回true,否则返回false. (2)Object.Equals (Object, Object)  该方法能够确定指定的两个Object实例是否相等.相等时返回true,否则返回false.此方法为静态方法.

一起学习《C#高级编程》2--比较对象的相等性

今后争取每两天能更新一次.平日的诱惑太多,双休只顾玩了,进度有点慢. 接上一讲的,类型的安全性,留下了点小尾巴——比较对象的相等性. C#有四种比较相等的方式:除了“==”运算符外,System.Object定义了3中方法:ReferenceEqual()方法和两种Equals(): 1.首先是“==”运算符: 对于值类型,“==”比较两个值是否相等:而对于引用类型,“==”则是比较两个对象的引用地址是否相同.这里有个特例,就是string字符串类型,“==”是比较字符串的值而不是引用地址,这是

C#编程(三十九)----------比较对象的相等性

比较对象的相等性 需要理解对象相等的机制对逻辑表达式的编程很重要,另外,对实现运算符重载和类型强制转换也很重要. 对象相等的机制有所不同,这取决于比较的是引用类型还是值类型. 比较引用类型的相等性 System.Object定义了三个不同的方法来比较对象的相等性:ReferenceEquals()和Equals()两个版本,再加上比较运算符,实际上有四种进行相等比较的方式. 1.ReferenceEquals()方法 以下是ReferenceEquals()方法的定义 public static

c# 面相对象2-之封装性

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 zhongqiuzuoye; public class Aodi extends Car{ public double price; public String model; public double speed; public Aodi(double price,String model,double speed)

读经典——《CLR via C#》(Jeffrey Richter著) 笔记_对象的相等性和同一性

[重写Equals注意的事项] 1. Equals 必须是自反的:--x.Equals(x)肯定为 true 2. Equals 必须是对称的:--x.Equals(y)肯定返回与y.Equals(x)相同的值 3. Equals 必须是可传递的:--x.Equals(y)返回true, y.Equals(z)返回true,则x.Equals(z)肯定返回true 4. Equals 必须是一致的.比较的两个值没有变,Equals返回的值(true或false)也不能变 5. 让类型实现 Sys

C++对象模型之详述C++对象的内存布局

在C++对象模型之简述C++对象的内存布局一文中.详细分析了各种成员变量和成员函数对一个类(没有不论什么继承的)对象的内存分布的影响,及详细解说了怎样遍历对象的内存,包含虚函数表.假设你在阅读本文之前.还没有看过C++对象模型之简述C++对象的内存布局一文,建议先阅读一下.而本文主要讨论继承对于对象的内存分布的影响,包含:继承后类的对象的成员的布局.继承对于虚函数表的影响.virtual函数机制怎样实现.执行时类型识别等. 因为在C++中继承的关系比較复杂.所以本文会讨论例如以下的继承情况: 1

php类和对象: clone 克隆

对象也能被“克隆” 在php5中,对象的传递方式默认为引用传递,如果我们想要在内存中生成两个一样的对象或者创建一个对象的副本,这时可以使用“克隆”. 通过 clone 克隆一个对象 对象的复制是通过关键字 clone 来实现的.用 clone 克隆出来的对象与原对象没有任何关系,它是把原来的对象从当前的位置重新复制了一份,也就是相当于在内存中新开辟了一块空间.通过关键字 clone 可以克隆一个对象,语法格式如下: $克隆对象名称=clone $原对象名称; __clone()方法 对象的__c