实施 EqualityCompare 与覆盖 GetHashCode 和 Equals
Implementing EqualityCompare vs overriding GetHashCode and Equals
我创建了两个几乎相同的 class。两者都代表一个 Pair (x,y),但在其中一个中,我覆盖了 GetHashCode 和 Equals 方法。有人告诉我,当 HashCode 不同时,Collections 将它们视为不同的元素,甚至懒得实际将它们与相等的元素进行比较。然而,事实证明,我为 class 实现了一个 EqualityComparer,它没有覆盖 GetHashCode 和 Equals,即使 HashCode 仍然不同,一切也能正常工作。
看看我的控制台项目:
using System;
using System.Collections.Generic;
using System.Linq;
namespace matrixExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Same Hash but no insertion: as expected");
HashSet<MyPair> hash = new HashSet<MyPair>();
MyPair one = new MyPair { X = 10, Y = 2 };
MyPair copyOfOne = new MyPair { X = 10, Y = 2 };
Console.WriteLine(one.GetHashCode() + " " + hash.Add(one));
Console.WriteLine(copyOfOne.GetHashCode() + " " + hash.Add(copyOfOne));
Console.WriteLine("-----------------------------------------");
Console.WriteLine("Different Hash but no insertion! why?");
HashSet<MyPairWithoutOverride> hash2 = new HashSet<MyPairWithoutOverride>(new SameHash());
MyPairWithoutOverride a1 = new MyPairWithoutOverride { X = 10, Y = 2 };
MyPairWithoutOverride a1copy = new MyPairWithoutOverride { X = 10, Y = 2 };
Console.WriteLine(a1.GetHashCode() + " " + hash2.Add(a1));
Console.WriteLine(a1copy.GetHashCode() + " " + hash2.Add(a1copy));
}
public class MyPair
{
public int X { get; set; }
public int Y { get; set; }
public override int GetHashCode()
{
return X * 10000 + Y;
}
public override bool Equals(object obj)
{
MyPair other = obj as MyPair;
return X == other.X && Y == other.Y;
}
}
public class MyPairWithoutOverride
{
public int X { get; set; }
public int Y { get; set; }
}
public class SameHash : EqualityComparer<MyPairWithoutOverride>
{
public override bool Equals(MyPairWithoutOverride p1, MyPairWithoutOverride p2)
{
return p1.X == p2.X && p1.Y == p2.Y;
}
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
}
}
}
你的问题就在这里
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
您 returning base.GetHashCode()
实际上是 SameHash
class 的哈希码。所以你实际上每次都return输入相同的哈希码。
如果您 return i.GetHashCode()
那么它将按预期运行。
我创建了两个几乎相同的 class。两者都代表一个 Pair (x,y),但在其中一个中,我覆盖了 GetHashCode 和 Equals 方法。有人告诉我,当 HashCode 不同时,Collections 将它们视为不同的元素,甚至懒得实际将它们与相等的元素进行比较。然而,事实证明,我为 class 实现了一个 EqualityComparer,它没有覆盖 GetHashCode 和 Equals,即使 HashCode 仍然不同,一切也能正常工作。
看看我的控制台项目:
using System;
using System.Collections.Generic;
using System.Linq;
namespace matrixExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Same Hash but no insertion: as expected");
HashSet<MyPair> hash = new HashSet<MyPair>();
MyPair one = new MyPair { X = 10, Y = 2 };
MyPair copyOfOne = new MyPair { X = 10, Y = 2 };
Console.WriteLine(one.GetHashCode() + " " + hash.Add(one));
Console.WriteLine(copyOfOne.GetHashCode() + " " + hash.Add(copyOfOne));
Console.WriteLine("-----------------------------------------");
Console.WriteLine("Different Hash but no insertion! why?");
HashSet<MyPairWithoutOverride> hash2 = new HashSet<MyPairWithoutOverride>(new SameHash());
MyPairWithoutOverride a1 = new MyPairWithoutOverride { X = 10, Y = 2 };
MyPairWithoutOverride a1copy = new MyPairWithoutOverride { X = 10, Y = 2 };
Console.WriteLine(a1.GetHashCode() + " " + hash2.Add(a1));
Console.WriteLine(a1copy.GetHashCode() + " " + hash2.Add(a1copy));
}
public class MyPair
{
public int X { get; set; }
public int Y { get; set; }
public override int GetHashCode()
{
return X * 10000 + Y;
}
public override bool Equals(object obj)
{
MyPair other = obj as MyPair;
return X == other.X && Y == other.Y;
}
}
public class MyPairWithoutOverride
{
public int X { get; set; }
public int Y { get; set; }
}
public class SameHash : EqualityComparer<MyPairWithoutOverride>
{
public override bool Equals(MyPairWithoutOverride p1, MyPairWithoutOverride p2)
{
return p1.X == p2.X && p1.Y == p2.Y;
}
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
}
}
}
你的问题就在这里
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
您 returning base.GetHashCode()
实际上是 SameHash
class 的哈希码。所以你实际上每次都return输入相同的哈希码。
如果您 return i.GetHashCode()
那么它将按预期运行。