2011-08-26 17 views
25

Quería crear un objeto tipo diccionario y pensé que la forma correcta sería implementar la interfaz IDictionary<K,V>, y usar la composición para incluir el diccionario subyacente. Empecé con el siguiente (K = string, V = int)¿Por qué el Diccionario de C# no implementa todo IDictionary?

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

Luego utiliza la capacidad "Implementar interfaz" de Visual Studio para apagar todos los métodos de cobertura que iba a necesitar.

no parecen Tres métodos de IDictionary de existir en Dictionary:

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

embargo the Microsoft documentation indica claramente que implementa DictionaryIDictionary. Entonces habría esperado que estos tres métodos estuvieran disponibles. Para copiar de la documentación, la definición de 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 

Estos tres métodos que faltan, creo, se encuentran en ICollection<>. Pero también lo son otros métodos como Clear() que tiene Dictionary.

Pregunta 1: ¿Cómo puede C# escapar sin implementar estos tres, y por qué es así? Sospecho que este es un error del compilador (para mi razonamiento, ver abajo). Pregunta 2: Alternativamente, ¿qué me estoy perdiendo?

He aquí por qué creo que podría ser un error del compilador. Examine el siguiente código:

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 

El método void Add(KeyValuePair<string, int> item) parece no estar en Dictionary<string,int> (ya que no compila), pero es en IDictionary<string,int>, y de alguna manera el compilador encuentre correctamente una implementación de la misma. Pregunta 3: ¿Qué está pasando?

Tenga en cuenta que la documentación de Microsoft para Dictionary<K,V> no especifica estos tres métodos.

Por último, en mi aplicación real, que terminé usando

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

en lugar de

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

por lo que los tres métodos fácilmente podrían trabajar.

Respuesta

44

El Dictionary<TKey, TValue> implementa estos métodos, simplemente lo hace explícitamente. Por lo tanto, debe acceder a través de la interfaz IDictionary<TKey, TValue>.

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

La implementación explícita funciona al especificar con precisión qué método de interfaz implementa un método de instancia en el punto de definición. Por ejemplo

interface IFoo { 
    void Method(); 
} 

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

class C2 : IFoo { 
    // Explicitly implements IFoo.Method 
    void IFoo.Method() { } 
} 
+1

Esa fue exactamente mi primera conjetura. ¿Sabes por qué esto no está especificado en la documentación de MSDN? Además, ¿por qué ocultaron esos métodos? –

+0

@the_drow, no estoy seguro de por qué no hacen esa distinción en la documentación ni estoy 100% seguro de por qué hicieron la elección. Mi primer instinto para este último es que querían proporcionar una sola sobrecarga de Agregar por defecto. – JaredPar

+6

@the_drow: en realidad se especifica en la documentación de MSDN. Solo tiene que desplazarse hacia abajo hasta "Implementaciones de interfaces explícitas" – Daniel

Cuestiones relacionadas