Object.ReferenceEquals(str1,str2) 将会返回真。2. 实现值类型的 Equals:我们如果想希望我们的 Class 实现值类型,那么有两个办法,第一个办法比较简单粗暴,直接重写 Equal 和 GetHashCode,一定要记住要重写 GetHashCode,比如我们可以写出下面的代码。
- string str1 = "Fuck";
- string str2 = "Fuck";
- class Test1
- {
- public string Name { get; set; }
- public Test1(string name)
- {
- Name = name;
- }
- public override bool Equals(object obj)
- {
- if (obj == null || obj.GetType() != typeof(Test1))
- return false;
- Test1 testObj = obj as Test1;
- return this.Name == testObj.Name;
- }
- public static bool operator==(Test1 t1, Test1 t2)
- {
- return t1.Equals(t2);
- }
- public static bool operator !=(Test1 t1, Test1 t2)
- {
- return !(t1 == t2);
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- }
- 这个时候我们可以把Test1来进行值的比较了,但是上面的代码并没有真正重载GetHashCode,以至于我们会导致下面的问题,我们写入下面的代码:
这个时候看上去还很正常,但是如果我们加一点测试:
- class Program
- {
- static void Main(string[] args)
- {
- Test1 t1 = new Test1("HaHa");
- Test1 t2 = new Test1("HaHa");
- Console.WriteLine("t1.Equals(t2)? {0}", t1.Equals(t2));
- Console.WriteLine("t1 == t2? {0}", t1 == t2);
- List list = new List();
- list.Add(t1);
- Console.WriteLine("list contains Test1(HaHa)? {0}", list.Contains(t2));
- Console.ReadKey();
- }
- }
这就出现了很奇怪的现象了,我们已经假定了我们的 Test1 是一个值类型了,我们如果把这个东西作为 HashSet 的类型或者 Dictionary 的键值的时候,却发现了这样的诡异的情况,我们认为相等的值不再相等。 这种情况的原因就是因为我们没有真正重写 GetHashCode,如果把 GetHashCode 的代码改成这样:
- class Program
- {
- static void Main(string[] args)
- {
- Test1 t1 = new Test1("HaHa");
- Test1 t2 = new Test1("HaHa");
- Console.WriteLine("t1.Equals(t2)? {0}", t1.Equals(t2));
- Console.WriteLine("t1 == t2? {0}", t1 == t2);
- ICollection list = new HashSet();
- list.Add(t1);
- Console.WriteLine("list contains Test1(HaHa)? {0}", list.Contains(t2));
- Dictionaryint> dict = new Dictionaryint>();
- dict.Add(t1, 2);
- Console.WriteLine("dict contains Test1(HaHa)? {0}", dict.Keys.Contains(t2));
- Console.ReadKey();
- }
- }
这样改动以后我们的程序将会出现正确的结果: 当然了正如我们上面所说的,我们可以通过实现 IEqualable<T> 的泛型接口来实现强类型的比较:
- public override int GetHashCode()
- {
- return Name.GetHashCode();
- }
如果实现了 IEqualable<T> 的泛型接口,那么 Equals 就没必要重载了,这就是我们经常使用的 StringBuilder 的是实现方式(不过 StringBuilder 并没有实现 IEqualable<T> 这个接口,而是直接重载了 Equals 这个方法)。 如果把 class 改为 struct,因为值类型不可能为 null,所以可以这样写:
- class Test : IEquatable
- {
- public Test(string name)
- {
- Name = name;
- }
- public bool Equals(Test other)
- {
- return this.Name == other.Name;
- }
- public override bool Equals(object obj)
- {
- return base.Equals(obj);
- }
- public override int GetHashCode()
- {
- return Name.GetHashCode();
- }
- public string Name { get; set; }
- }
- struct Test1
- {
- public string Name { get; set; }
- public Test1(string name)
- {
- Name = name;
- }
- public override bool Equals(object obj)
- {
- if (obj is Test1)
- {
- return this.Name == ((Test1)obj).Name;
- }
- return false;
- }
- public static bool operator==(Test1 t1, Test1 t2)
- {
- return t1.Equals(t2);
- }
- public static bool operator!=(Test1 t1, Test1 t2)
- {
- return !(t1.Equals(t2));
- }
- public override int GetHashCode()
- {
- return Name.GetHashCode();
- }
- }
来源: