我有一个IPv4列表,作为页面访问中的byte []。为了获得唯一列表,我想将它们添加到HashSet中。使用以下代码会将重复的条目放入HashSet中,我以前认为这是不可能的。
byte[] a = new byte[] {0,0,0,1};
byte[] b = new byte[] {0,0,0,1};
HashSet<byte[]> hashBytes = new HashSet<byte[]>();
hashBytes.Add(a);
hashBytes.Add(b);
我希望哈希集仅包含a,但同时包含a和b。
编辑:根据评论者,我在附加代码中添加了
public class IPComparer : IEqualityComparer<byte[]>
{
public bool Equals(byte[] a, byte[] b)
{
//They are not an IP address
if (a.Length != 4 && b.Length != 4)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public int GetHashCode(byte[] a)
{
uint b = 0;
for (int i = 0; i < a.Length; i++)
{
b = ((b << 23) | (b >> 9)) ^ a[i];
}
return unchecked((int)b);
}
我还使用新的HashSet(IPComparer)而不是常规比较器制作了HashSet。结果没有改变。
答案 0 :(得分:10)
要在哈希集中使用,您的类必须正确实现GetHashCode
和Equals
。 byte[]
并非如此-数组通常不会覆盖这些方法,因此哈希集将基于引用相等而非值相等进行比较。
最简单的解决方案是使用IPAddress
而不是byte[]
。如果这不是一个选择,则必须编写自己的比较器并将其传递给哈希集。您可以使用SequenceEquals
来按值比较数组;良好的哈希值有点棘手,因为如果不缓存该值,这将非常慢-您可能需要创建自己的类,其中包含byte[]
并实现Equals
和{ {1}}正确(哪种会让您回到GetHashCode
:)。