Why doesn't the C# Dictionary implement all of IDictionary?
Asked Answered
N

1

29

I wanted to create a Dictionary-like object and thought the correct way would be to implement the IDictionary<K,V> interface, and use composition to include the underlying dictionary. I began with the below (K=string, V=int)

public class DictionaryLikeObject : IDictionary<string,int> {
  Dictionary<string,int> _backingDictionary = new Dictionary<string,int>();
}

Then I used Visual Studio's "Implement Interface" ability to stub out all the cover methods that I would need.

Three methods of IDictionary do not seem to exist in Dictionary:

void Add(KeyValuePair<string, int> item);
void CopyTo(KeyValuePair<string, int>[] array, int arrayIndex);
bool Remove(KeyValuePair<string, int> item);

Yet the Microsoft documentation clearly indicates that Dictionary implements IDictionary. So I would have expected these three methods to be available. To copy from the documentation, the definition of Dictionary<K,V>

[SerializableAttribute]
[ComVisibleAttribute(false)]
public class Dictionary<K, V> : IDictionary<K, V>, 
ICollection<KeyValuePair<K, V>>, IEnumerable<KeyValuePair<K, V>>, 
IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback

These three missing methods, I believe, are found in ICollection<>. But so are other methods such as Clear() that Dictionary does have.

Question 1: How can C# get away without implementing these three, and why is this so? I suspect this is a compiler error (for my reasoning, see below). Question 2: Alternatively, what am I missing?

Here's why I think it might be a compiler error. Examine the following code:

Dictionary<string, int> dictionary1 = new Dictionary<string, int>();
IDictionary<string, int> dictionary2 = new Dictionary<string, int>();
KeyValuePair<string, int> item = new KeyValuePair<string, int>("test", 1);
//dictionary1.Add(item); // compile error: No overload for method 'Add' takes 1 argument
dictionary2.Add(item); // works like a charm
Debug.WriteLine(@"dictionary2[""test""] = {0}", dictionary2["test"]); // outputs: dictionary2["test"] = 1

The method void Add(KeyValuePair<string, int> item) appears not to be in Dictionary<string,int> (since it doesn't compile), but it is in IDictionary<string,int>, and somehow the compiler does properly find an implementation of it. Question 3: What's going on?

Note that the Microsoft documentation for Dictionary<K,V> does not specify these three methods.

Lastly, in my actual implementation, I ended up using

IDictionary<string,int> _backingDictionary = new Dictionary<string,int>();

instead of

Dictionary<string,int> _backingDictionary = new Dictionary<string,int>();

so that all three methods could easily work.

Noonday answered 26/8, 2011 at 21:15 Comment(0)
O
48

The Dictionary<TKey, TValue> does implement these methods, it just does so explicitly. Hence you must access it via the IDictionary<TKey, TValue> interface.

Dictionary<string, string> map = ...;
KeyValuePair<string, string> pair = ...;
map.Add(pair);  // Compilation Error
((IDictionary<string, string>)map).Add(pair);  // Works

Explicit implementation works by specifying precisely which interface method an instance method implements at the point of definition. For example

interface IFoo {
  void Method(); 
}

class C1 : IFoo {
  // Implicitly implements IFoo.Method
  public void Method() { }
}

class C2 : IFoo {
  // Explicitly implements IFoo.Method
  void IFoo.Method() { }
}
Oliviero answered 26/8, 2011 at 21:17 Comment(4)
That was exactly my first guess. Do you know why this isn't specified in the MSDN documentation? Also, why did they hide those methods?Onomastics
@the_drow, I'm unsure why they don't make that distinction in the documentation nor am I 100% sure why they made the choice. My first instinct for the latter is they wanted to provide a single overload of Add by default.Oliviero
@the_drow: It is actually specified in the MSDN documentation. You just have to scroll way down to "Explicit Interface Implementations"Gospodin
So the explicit/implicit answer nails this question. JaredPar's answer, coupled with a careful reading Microsoft's documentation of explicit/implicit implementation link and the StackOverflow thread link was truly helpful. Also, thanks to Daniel for pointing out that the MSDN documentation does list "explicit implementations".Noonday

© 2022 - 2024 — McMap. All rights reserved.