Jim G.
Jim G.

Reputation: 15365

C# Dictionary: Each Key Has An Identical Value - Can I Remove the Redundancy?

Consider the following code, where each key has an identical value:

IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>();
quarterbackDictionary.Add("Manning", "Manning");
quarterbackDictionary.Add("Brady", "Brady");
quarterbackDictionary.Add("Rivers", "Rivers");

My question:

  • Can I remove the redundancy, so that I don't have to repeat each string twice, similar to the following:
IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>();
quarterbackDictionary.Add("Manning");
quarterbackDictionary.Add("Brady");
quarterbackDictionary.Add("Rivers");

FYI:

Upvotes: 1

Views: 936

Answers (5)

dkackman
dkackman

Reputation: 15549

You could also inherit from System.Collections.ObjectModel.KeyedCollection.

class MyDictionary : KeyedCollection<string, string>
{
    protected override string GetKeyForItem(string item)
    {
        return item;
    }
}

var d = new MyDictionary();
d.Add("jones");
d.Add("jones");   // this will except

Upvotes: 1

driis
driis

Reputation: 164291

You could wrap a HashSet<string> in your own class, and have it throw an exception if you try to add the same key twice.

It won't be much trouble to define that class, in fact, here is a possible implementation that you can tweak to fit your needs:

    public class UniqueHashSet<T> : ICollection<T>
    {
        private readonly HashSet<T> innerSet = new HashSet<T>();

        public void Add(T item)
        {
            if (innerSet.Contains(item))
                throw new ArgumentException("Element already exists", "item");
            innerSet.Add(item);
        }

        public void Clear()
        {
            innerSet.Clear();
        }

        public bool Contains(T item)
        {
            return innerSet.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            innerSet.CopyTo(array, arrayIndex);
        }

        public bool Remove(T item)
        {
            return innerSet.Remove(item);
        }

        public int Count
        {
            get { return innerSet.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return innerSet.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return innerSet.GetEnumerator();
        }
    }

As the other answers mention, you could also make it an extension method. I think you could certainly do this, unless you need to be absolutely sure that you cannot add the same item twice (if you do it the extension method way, one could still call the regular .Add method).

Upvotes: 11

mrydengren
mrydengren

Reputation: 4260

Perhaps you could use an extension method

public static class DictionaryExtensions
{
    public static void Add(this Dictionary<string, string> dictionary,  
        string keyAndValue)
    {
        string value;
        if (dictionary.TryGetValue(keyAndValue, out value))
        {
            throw new Exception();
        }

        dictionary.Add(keyAndValue, keyAndValue);
    }
}

Upvotes: 1

philsquared
philsquared

Reputation: 22493

Add an extension method to HashSet, say AddUnique, which just calls Add and throws if the return is false.

Upvotes: 3

Ryan Lundy
Ryan Lundy

Reputation: 210090

Inherit from System.Collections.ObjectModel.Collection and override InsertItem (which is protected).

Then you can do your duplicate check and throw when someone inserts a duplicate item. InsertItem is called on any of the methods that can put in a new item: Add, Insert, etc.

Upvotes: 1

Related Questions