views:

199

answers:

2

Is there a collection (apart from Dictionary) in the .NET framework (3.5) that throws an exception when a duplicate is added?

HashSet does not throw an exception here:

HashSet<string> strings = new HashSet<string>();
strings.Add("apple");
strings.Add("apple");

Whereas the Dictionary does:

Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("dude", "dude");
dict.Add("dude", "dude"); //throws exception

EDIT: Is there a collection without (Key, Value) that does this? I also want AddRange if possible...

I rolled my own:

public class Uniques<T> : HashSet<T>
{

    public Uniques()
    { }

    public Uniques(IEnumerable<T> collection)
    {
        AddRange(collection);
    }

    public void Add(T item)
    {
        if (!base.Add(item))
        {
            throw new ArgumentException("Item already exists");
        }
    }


    public void AddRange(IEnumerable<T> collection)
    {
        foreach (T item in collection)
        {
            Add(item);
        }
    }
}
+2  A: 

But the HashSet.Add method returns false if the value already is present - isn't that enough?

HashSet<string> set = new HashSet<string>();
...
if (!set.Add("Key"))
    /* Not added */
Björn
It allows you to add without the cost of checking Contains before, two operations in one call. There is no TryAdd on the Dictionary<,>.
Guillaume
Ah, ok. Good point.
Björn
I prefer it but it's strange as ICollection.Add returns void and others collection that disallow duplicates throw...
Guillaume
Ok, I sort of wanted AddRange functionality. Thanks
geejay
A: 

If you're looking for AddRange style functionality, look at C5. The collections in the C5 family have a lot more functionality exposed in their interfaces, including a function AddAll that takes an enumerable, adding all the items in the enumerable to the collection in turn.

EDIT: Also note that the C5 collections implement the System.Collections.Generic ICollection and IList interfaces where appropriate, so can be used as the implementation even in systems that expect those interfaces.

Marcus Griep