13

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);
        }
    }
}
geejay
  • 5,440
  • 8
  • 50
  • 60

3 Answers3

19

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
  • 29,019
  • 9
  • 65
  • 81
0

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
  • 8,156
  • 1
  • 23
  • 24
0

To add to Bjorn's answer, if you also want a function like IList.AddRange type of function with HashSet<T>, you can use HashSet<T>.UnionWith (from MSDN):

HashSet(T).UnionWith Method

Modifies the current HashSet object to contain all elements that are present in itself, the specified collection, or both.

public void UnionWith(
    IEnumerable<T> other
)

Only problem might be: I'm pretty sure this requires the .NET Framework 3.5 SP1 and up.

Community
  • 1
  • 1
Gutblender
  • 1,340
  • 1
  • 12
  • 25