2011-08-26 15 views
25

Chciałem stworzyć obiekt podobny do Słownika i pomyślałem, że właściwym sposobem będzie implementacja interfejsu IDictionary<K,V> i użycie kompozycji do uwzględnienia podstawowego słownika. I zaczęło się poniżej (K = string, V = int)Dlaczego słownik C# nie implementuje całego IDictionary?

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

Następnie użyłem Visual Studio "zaimplementować interfejs" zdolność odgałęzienie wszystkie metody tytułowych że będę potrzebował.

Trzy sposoby IDictionary nie wydają się istnieć w Dictionary:

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

the Microsoft documentation jednak wyraźnie wskazuje, że Dictionary realizuje IDictionary. Tak więc oczekiwałbym, że te trzy metody będą dostępne. Aby skopiować z dokumentacją definicję 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 

Te trzy brakujące metod, jak sądzę, można znaleźć w ICollection<>. Ale tak samo są inne metody, takie jak Clear(), które ma Dictionary.

Pytanie 1: Jak można C# uciec bez wdrożenia tych trzech i dlaczego tak się dzieje? Podejrzeń, że jest to błąd kompilatora (dla mojego rozumowania, patrz poniżej). Pytanie 2: Alternatywnie, czego mi brakuje?

Oto dlaczego myślę, że może to być błąd kompilatora. Zbadać następujący kod:

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 

Sposób void Add(KeyValuePair<string, int> item) nie wydaje się być w Dictionary<string,int> (ponieważ nie skompilować), ale jest w IDictionary<string,int> i jakoś kompilator ma właściwie znaleźć implementacji. Pytanie 3: Co się dzieje?

Należy pamiętać, że dokumentacja Microsoft dla Dictionary<K,V> nie określa tych trzech metod.

Wreszcie w mojej rzeczywistej realizacji, skończyło się za pomocą

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

zamiast

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

tak, że wszystkie trzy metody mogą łatwo pracować.

Odpowiedz

44

Urządzenie Dictionary<TKey, TValue> implementuje te metody, po prostu robi to jawnie. Dlatego musisz uzyskać do niego dostęp poprzez interfejs IDictionary<TKey, TValue>.

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

Wyraźna implementacja polega na precyzyjnym określeniu, która metoda interfejsu implementowana jest przez metodę instancji w punkcie definicji. Na przykład:

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

To było dokładnie moje pierwsze przypuszczenie. Czy wiesz, dlaczego nie jest to określone w dokumentacji MSDN? Dlaczego ukryli te metody? –

+0

@the_drow, nie jestem pewien, dlaczego nie dokonują tego rozróżnienia w dokumentacji, ani nie jestem w 100% pewien, dlaczego dokonali wyboru. Moim pierwszym instynktem dla tych drugich jest to, że chcieli zapewnić pojedyncze przeciążenie domyślnie przez Add. – JaredPar

+6

@the_drow: Jest to faktycznie określone w dokumentacji MSDN. Trzeba tylko przewinąć w dół do "Jawnych implementacji interfejsu". – Daniel

Powiązane problemy