HashSet <byte []>包含重复项

时间:2019-09-11 18:42:59

标签: c#

我有一个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。结果没有改变。

1 个答案:

答案 0 :(得分:10)

要在哈希集中使用,您的类必须正确实现GetHashCodeEqualsbyte[]并非如此-数组通常不会覆盖这些方法,因此哈希集将基于引用相等而非值相等进行比较。

最简单的解决方案是使用IPAddress而不是byte[]。如果这不是一个选择,则必须编写自己的比较器并将其传递给哈希集。您可以使用SequenceEquals来按值比较数组;良好的哈希值有点棘手,因为如果不缓存该值,这将非常慢-您可能需要创建自己的类,其中包含byte[]并实现Equals和{ {1}}正确(哪种会让您回到GetHashCode:)。