Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 815
Marc Meketon Avatar asked Aug 26 '11 21:08

Marc Meketon


People also ask

Why is there no string in C?

Both Java and Python have the concept of a "string", C does not have the concept of a "string". C has character arrays which can come in "read only" or manipulatable. A character array is a sequence of contiguous characters with a unique sentinel character at the end (normally a NULL terminator '\0' ).

Why is C not A or B?

Because C comes after B The reason why the language was named “C” by its creator was that it came after B language. Back then, Bell Labs already had a programming language called “B” at their disposal.

Why C has no exception handling?

As such, C programming does not provide direct support for error handling but being a system programming language, it provides you access at lower level in the form of return values. Most of the C or even Unix function calls return -1 or NULL in case of any error and set an error code errno.

Why array bounds checking is not available in C?

This is due to the fact that C++ does not do bounds checking. Languages like Java and python have bounds checking so if you try to access an out of bounds element, they throw an error. C++ design principle was that it shouldn't be slower than the equivalent C code, and C doesn't do array bounds checking.


1 Answers

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() { } } 
like image 53
JaredPar Avatar answered Sep 22 '22 01:09

JaredPar