2017-01-24 2 views
0

Mein Ziel ist es, ein Wörterbuch, das eindeutige Schlüssel und Werte hat, die ich mit einem zusätzlichen HashSet lösen. Ich möchte eine Basisklasse haben, von der spezifischere Typen erben.Wie IDIssiction Interface und Unterklasse korrekt zu implementieren ist

Wie ich verstanden habe, ist die add-Methode der Dictionary-Klasse nicht virtuell und kann daher nicht überschrieben werden. Der einzige Weg, dies zu tun, ist die Implementierung der IDictionary-Schnittstelle.

So ist die Grundstruktur meiner Basiswörterbuch-Klasse ist:

public class BaseCustomDictionary<TKey,TValue>:IDictionary<TKey,TValue> { 
    public virtual Dictionary<TKey,TValue> InternalDict { 
     get; 
     set; 
    } 

    public BaseCustomDictionary() { 
     this.InternalDict = new Dictionary<TKey,TValue>(); 
    } 

    // Here I start implementing all the required methods, e.g. Add, TryGetValue 
    public virtual void Add(TKey key, TValue value) { 
     InternalDict.Add(key, value); 
    } 

    public bool TryGetValue (TKey key, out string value) { 
     return InternalDict.TryGetValue (key, out value); 
    } 

    // And so on and so forth 
} 

Jetzt habe ich eine konkrete Unterklasse haben will, die int s als Schlüssel und string als Wert hat:

public class IntStringDictionary<TKey,TValue>:BaseCustomDictionary<TKey,TValue> { 
    public override Dictionary<int,string> InternalDict { 
     get; 
     set; 
    } 

    HashSet<string> UniqueValues; 

    public IntStringDictionary() { 
     InternalDict = new Dictionary<int,string>(); 
     UniqueValues = new HashSet<string>(); 
    } 

    public override void Add (TKey key, TValue value) { 
     if (InternalDict.ContainsKey (key)) { 
      return; 
     } 

     string randomStr = RandomString(); 

     if (!UniqueValues.Add(randomStr)) { 
      Add(key,value); 
      return; 
     } else { 
      InternalDict.Add(key,randomStr); 
      return 
     } 
    } 
} 

I Here auf alle möglichen Probleme stoßen. Erste ist The best overloaded method match for 'System.Collections.Generic.Dictionary<int,string>.ContainsKey(string) has some invalid arguments'. Cannot convert type 'TKey' to 'string'. Zustimmen. Also ändere ich die InternalDict zu new Dictionary<TKey,short>() und die Parameter für Add zu (TKey key, TValue value).

Das nächste Problem ist, wie auf Methoden zugegriffen wird. Sagen meine Implementierung sieht wie folgt aus:

public static IntStringDictionary<int,string> myDict = new IntStringDictionary<int,string>(); 

// Assuming the class is named Constructor 
public Constructor() { 
    myDict.Add(1,"foobar"); 
} 

public static string GetValue (int key) { 
    string value; 
    myDict.TryGetValue(key, out value); 

    if (value == '') { 
     throw new NullReferenceException ("Value not found for given key"); 
    } 

    return value; 
} 

Diese GetValue Methode der implementierten Ausnahme immer aus, wenn ich 1 passieren, und ich verstehe wirklich nicht, warum. Ich debuggte den Code und kann feststellen, dass das 'InternalDict' tatsächlich den Schlüssel 1 und den Wert foobar. The TryGetValue call on myDict jumps into the implementation of the BaseCustomDictionary class and writes an empty string into the value` variable enthält.

Natürlich könnte ich jetzt meine eigene TryGetValue in meiner Unterklasse implementieren, aber das scheint den Zweck der Unterklassen zu besiegen, wenn ich jede Methode implementieren muss.

public bool TryGetValue(TKey key, out int value) { 
    return InternalDict.TryGetValue(key, out value); 
} 

Ich fühle mich wie etwas grundlegend falsch mit der Vererbung tun.

Antwort

0

Die Unterklasse hat keinen Grund, generisch zu sein; Sein Grund dafür ist, Typparameter für seine Basisklasse anzugeben. Deklarieren Sie die Unterklasse wie folgt aus:

public class IntStringDictionary : BaseCustomDictionary<int,String> 
{ 
} 

Sie sollten keine Mitglieder für die Implementierung, wenn Ihre Basisklasse nicht abstrakt ist. In der Tat ist mir nicht klar, warum Sie nicht nur BaseCustomDictionary<int, String> instanziieren, wie Sie mit Dictionary, aber es gibt gültige Gründe für die Unterklasse, die für Ihre Frage nicht relevant wäre.

Übrigens dies in der generischen Basis nicht kompiliert:

public bool TryGetValue (TKey key, out string value) { 
    return InternalDict.TryGetValue (key, out value); 
} 

Dies wird - der value Parameter muss TValue sein. Aber ich vermute, das war nur ein Fehler beim Kopieren und Einfügen beim Verfassen Ihrer Frage.

public bool TryGetValue (TKey key, out TValue value) { 
    return InternalDict.TryGetValue (key, out value); 
} 
0

Sie tun falsch Dinge, da dies:

public class IntStringDictionary: BaseCustomDictionary

einen int String-Wörterbuch zu erstellen, die die gleiche Funktionalität wie ein BaseCustomDictionary hat, Sie dies nicht tun vererben . Sie tun nur:

var myDict = new BaseCustomDictionary<int, string>(); 

Einfach so!

Sie erben nur, wenn Sie eine neue Funktionalität zu BaseCustomDictionary hinzufügen möchten. Von Ihrer Frage kann ich nicht sehen, welches neue Verhalten Sie zu Ihrem BaseCustomDictionary hinzufügen möchten.

+0

Es ist hauptsächlich die "Add" -Methode. Abhängig vom Typ meiner Werte werde ich eine andere Methode aufrufen, um einen Pseudozufallswert zu erzeugen. Ansonsten weiß ich nicht, wie ich diese Unterscheidung in der 'BaseCustomDictionary'-Klasse hinzufügen könnte. – ShitakeOishii

+0

Leider habe ich die Add-Methode nicht bemerkt. Aber Ihre Add-Methode-Implementierung scheint seltsam. Ich denke, Sie sollten diese Logik dem Benutzer der Wörterbuchklasse überlassen. Eine andere Möglichkeit besteht darin, dem BaseCustomDictionary Erweiterungsmethoden hinzuzufügen. – Sweeper

Verwandte Themen