List broken or pebkac?

Either the Generic List (and HashSet) is broken or ... pebkac

This unworthy test-program outputs the following:

System.Byte[]
6:2 3 4 5 6 7
True        // as expected
System.Byte[]
6:3 4 5 6 7 8
True        // as expected
System.Byte[]
6:3 4 5 6 7 8
False       // oops ... something's very wrong
System.Byte[]
6:3 4 5 6 7 8
False       // oops ... something's very wrong

I just don't get it, REALLY don't get it why the last two ones are "False" :-/

using System.Collections.Generic;
using System.Collections;
using System;

public class HashSetTest {

    public static HashSet<byte[]> SomeThing=new HashSet<byte[]>();

    public static void Write(byte[] pebkac) {
        Console.Write("{0}:",pebkac.Length);
        foreach(var i in pebkac) {
            Console.Write("{0} ",i);
        }
        Console.WriteLine();
    }

    public static void Main() {
        byte[] test1= {1,2,3,4,5,6};
        byte[] test2= {2,3,4,5,6,7};
        byte[] test3= {3,4,5,6,7,8};

        List<byte> test4=new List<byte>();
        test4.AddRange(test3);

        byte[] test5=new byte[6];
        var i=0;
        foreach(byte j in test3) {
            test5[i++]=j;
        }

        SomeThing.Add(test1);
        SomeThing.Add(test2);
        SomeThing.Add(test3);

        Console.WriteLine(test2);
        Write(test2);
        Console.WriteLine(SomeThing.Contains(test2));

        Console.WriteLine(test3);
        Write(test3);
        Console.WriteLine(SomeThing.Contains(test3));

        Console.WriteLine(test4.ToArray());
        Write(test4.ToArray());
        Console.WriteLine(SomeThing.Contains(test4.ToArray()));

        Console.WriteLine(test5);
        Write(test5);
        Console.WriteLine(SomeThing.Contains(test5));
    }
}
Jon Skeet
people
quotationmark

Nope, nothing's broken - but arrays don't override Equals or GetHashCode. So a HashSet<byte[]> is just checking for the presence of the exact object that the key refers to. It's not looking for "an array with an equivalent sequence of bytes".

You haven't added test5 to the set, so SomeThing.Contains(test5) won't be true - and calling SomeThing.Contains(anyListOfByte.ToArray()) will return false because that will create a new array each time.

If you want HashSet<T> to use a different meaning of equality, you can do so by passing an IEqualityComparer<T> to the constructor.

people

See more on this question at Stackoverflow