C# ==、Equals和ReferenceEquals
作者:互联网
值类型
== : 比较两者的“内容”是否相同,即“值”是否一样
Equals:比较两者的“内容”是否相同,即“值”是否一样
ReferenceEquals:返回false,因为会对值类型进行装箱再进行比较
引用类型
== : 比较的是引用变量指向的对象在堆中的存储地址是否一样
Equals: 比较的是引用变量指向的对象在堆中的存储地址是否一样
ReferenceEquals: 比较的是引用变量指向的对象在堆中的存储地址是否一样
注意:对于String类型都是比较String的值是否一样
如果自定义的类型重写了Object的Equals方法,则也需要重写GetHashCode方法,如果重写了Equals但没有重写GetHashCode的话在以该自定义类型为键的哈希表中(如Dictionary和Hashtable)就会出问题(比如永远找不到指定key)
如下:
a) 定义重写了Equals但没有重写GetHashCode的自定义类型_20210304_2_Model
public class _20210304_2_Model { public int Age { get; set; } public override bool Equals(object obj) { var tempObj = obj as _20210304_2_Model; // 转换不成功返回null if (tempObj == null) return false; return this.Age == tempObj.Age; } }
b) 测试代码如下
Console.WriteLine("是否相等:"+(new _20210304_2_Model { Age = 10 }.Equals(new _20210304_2_Model { Age = 10 }))); Dictionary<_20210304_2_Model, int> dics = new Dictionary<_20210304_2_Model, int>(); dics.Add(new _20210304_2_Model { Age = 10 }, 10); var res = dics[new _20210304_2_Model { Age = 10 }]; // 报错找不到
c) 运行结果
d) 原因:对于Dictionary来说,虽然我们存储的时候是键值对,但是CLR会先把key转成HashCode并且验证Equals后再做存储(即当key的HashCode和Equals都不相等时才会存储新的键),根据key取值的时候也是把key转换成HashCode并且验证Equals后再取值(当Key的HashCode和Equals都相等时来取键值),一定要注意验证时HashCode和Equals的关系是并且(&&)的关系。也就是说,只要GetHashCode和Equlas中有一个方法没有重写,在验证时没有重写的那个方法会调用基类的默认实现,而这两个方法的默认实现都是根据内存地址判断的,也就是说,其实一个方法的返回值永远会是false。其结果就是,存储的时候你可能任性的存,在取值的时候就是你哭着找不着娘了。
在重写Object类的GetHashCode方法时也要注意:
如果两个对象比较相等(Equals返回true),则每个对象的GetHashCode方法必须返回相同的值。 但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值。
比如如下重写:
public class _20210304_2_Model { public int Age { get; set; } public override bool Equals(object obj) { var tempObj = obj as _20210304_2_Model; // 转换不成功返回null if (tempObj == null) return false; return this.Age == tempObj.Age; } public override int GetHashCode() { return this.Age; } }
测试代码:
public void Run() { Console.WriteLine("是否相等:"+(new _20210304_2_Model { Age = 10 }.Equals(new _20210304_2_Model { Age = 10 }))); Dictionary<_20210304_2_Model, int> dics = new Dictionary<_20210304_2_Model, int>(); dics.Add(new _20210304_2_Model { Age = 10 }, 10); dics.Add(new _20210304_2_Model { Age = 10 }, 10); // 无法再添加了,因为key:new _20210304_2_Model { Age = 10 }的Equals和GetHashCode比较都一样 var res = dics[new _20210304_2_Model { Age = 10 }]; }
运行结果:
参考文档:https://www.cnblogs.com/xiaochen-vip8/p/5506478.html
微软官方GetHashCode文档:https://docs.microsoft.com/ZH-CN/dotnet/api/system.object.gethashcode?view=netcore-3.1
对象和引用变量关系:https://www.cnblogs.com/zsupreme/p/13406227.html
.NET 中间语言示例解析:https://docs.microsoft.com/zh-tw/previous-versions/dd229210(v=msdn.10)
标签:10,20210304,C#,Age,Equals,new,Model,ReferenceEquals 来源: https://www.cnblogs.com/tomorrow0/p/14484959.html