C#中有一共有四种相等性判断方法:
//Object中定义的三个方法 public static bool ReferenceEquals(object objLeft, object objRight); public static bool Equals(object objLeft, object objRight); public virtual bool Equals(object obj); //双等号 public static bool operator == (MyClass left, MyClass right)
①Object.ReferenceEquals(left, right)静态方法:从名称中便可知它用来比较两者是否是相同的引用,我们也永远不应该去重写该方法。它对于值类型对象的比较永远返回false;对于两个null的比较永远返回true。
②Object.Equals(left, right)静态方法:该方法也永远不需要重写,因为它最终会把判断权交给参数left的实例Equls方法(代码如下),因此没有必要重写该方法,只需要保证实例Equals返回想要的结果即可:
public static bool Equals(object left, object right) { if(object.ReferenceEquals(left,right)) //如果引用相同,则必定相等(包含两个都是null的情况) { return true; } if(object.ReferenceEquals(left ,null)|| object.ReferenceEquals(null,right)) //若只有一个是null,则必定不等 { return false; } return left.Equals(right);//两个都不是null,且也不是同一个引用,则根据left的实例Equals方法来判断。 }
③Object中的实例方法Equals,因为它是虚方法,所以可以在其他类中重写它。该方法的默认实现还是比较两者是否为同一个引用,即相当于ReferenceEquals。但是微软在所有值类型的基类System.ValueType中重写了该方法,用来比较值相等。
重写Equals应该遵循的原则:自反性、对称性、传递性。即:a=a;若a=b,则b=a;若a=b,b=c,则a=c;另外两个对象要么相等要不不等,所以该方法不应该抛出异常。下面是重写模板:
public class MyClass:IEquatable<MyClass> { //重写Object中的Equals方法 public override bool Equals(object obj) { if (object.ReferenceEquals(obj, null)) //首先判断obj不能为空,否则后面对obj调用任何方法都将报错 { return false; } if(object.ReferenceEquals(this,obj)) //在C#中this永远不会为空 { return true; } if(this.GetType() != obj.GetType()) { return false; } return this.Equals(obj as MyClass); } //实现IEquatable<T>中的Equals方法 public bool Equals(MyClass other) { //省略 return true; } }
④比较运算符==:对于引用类型,默认是比较引用的(System.String除外),对于值类型默认比较值,对于自定义的结构,如果不显示重载operator ==方法,则无法使用==。
C#中的ReferenceEquals、Equals以及==,布布扣,bubuko.com
C#中的ReferenceEquals、Equals以及==
原文:http://www.cnblogs.com/ArtofDesign/p/3615212.html