(一):比较对象的方法
概念有点多,看看就行了:
1:ReferenceEquals:
Object.ReferenceEquals(left, right)静态方法:从名称中便可知它用来比较两者是否是相同的引用,我们也永远不应该去重写该方法。它对于值类型对象的比较永远返回false;对于两个null的比较永远返回true。此方法必须使用类来调用。
cat f1 = new cat(5); cat f2 = new cat(5); // ReferenceEquals Console.WriteLine("ReferenceEquals:"+cat.ReferenceEquals(f1,f2));
2:实例Equals
Equals()虚拟版本的System.Object实现代码也比较引用。但因为这个方法是虚拟的(虚方法),所以可以在自己的类中重写它,按值来比较对象。特别是如果希望类的实例用作字典中的键,就需要重写这个方法,以比较值。否则,根据重写Object.GetHashCode()的方式,包含对象的字典类要么不工作,要么工作的效率非常低。在重写Equals()方法时要注意,重写的代码不会抛出异常。
重写Equals应该遵循的原则:自反性、对称性、传递性。即:a=a;若a=b,则b=a;若a=b,b=c,则a=c;另外两个对象要么相等要不不等,所以该方法不应该抛出异常。
cat f1 = new cat(5); cat f2 = new cat(5); // object.Equals Console.WriteLine("Equals:" + cat.Equals(f1, f2));
3:静态Equals
Object.Equals(left, right)静态方法:该方法也永远不需要重写,因为它最终会把判断权交给参数left的实例Equls方法,因此没有必要重写该方法,只需要保证实例Equals返回想要的结果即可。
cat f1 = new cat(5); cat f2 = new cat(5); // Equals Console.WriteLine("Equals:" + f1.Equals(f2));
4:相等运算符==
比较运算符==:对于引用类型,默认是比较引用的(System.String除外)来源,对于值类型默认比较值,对于自定义的结构,如果不显示重载operator ==方法,则无法使用==。
由于在C#中要求比较运算符必须成对重载,重载==运算符的同时也必须重载!=运算符,否则也会产生编译错误。
如果要重载的话,运算符"=="、"!=" 与 Equals方法、GetHashCode方法应该同时被重载,因为他们应该保持同样的相等逻辑。但不要再==中调用Equals,最好是在Equals中调用==。
cat f1 = new cat(5); cat f2 = new cat(5); // == Console.WriteLine("==:" + (f1 == f2)); static void Main(string[] args) { cat f1 = new cat(5); cat f2 = new cat(5); // ReferenceEquals Console.WriteLine("ReferenceEquals:"+cat.ReferenceEquals(f1,f2)); // object.Equals Console.WriteLine("Equals:" + cat.Equals(f1, f2)); // Equals Console.WriteLine("Equals:" + f1.Equals(f2)); // == Console.WriteLine("==:" + (f1 == f2)); }
以上代码输出都是false:因为f1是一个内存栈,f2是一个内存栈。所以其二者不想等
要想使以上等式相等。
static void Main(string[] args) { cat f1 = new cat(5); cat f2 = f1; // ReferenceEquals Console.WriteLine("ReferenceEquals:"+cat.ReferenceEquals(f1,f2)); // object.Equals Console.WriteLine("Equals:" + cat.Equals(f1, f2)); // Equals Console.WriteLine("Equals:" + f1.Equals(f2)); // == Console.WriteLine("==:" + (f1 == f2)); }
这样以上输出就都是true了。
(二):重写实例Equals方法:
在类中使用override进行重写,返回值类型是布尔类型。
// 重写之后,Equals比较的就是a的值,如果a的值相同,就是true public override bool Equals(object obj) { cat f3 = (cat)obj; if(f3.a == this.a) { return true; }else{ return false; } }
从以上的实例可以看出:重写之后Equals比较的是对象中的a的值,a相等,就是true。
而且我们也可以看出,重写实例Equals方法,静态Equals方法也会发生改变。