Modifyinig在词典中添加:reimplement IDictionary vs从Dictionary继承

时间:2015-08-07 10:05:36

标签: c#

所以,我要说我需要在Add中重新定义Dictionary<string, string>

解决方案A:

public class ImplementedDict : IDictionary<string, string>
{
    private readonly Dictionary<string, string> _data = new Dictionary<string, string>();
    public void Add(string key, string value)
    {
        _data.Add(key, value);
    }
}

解决方案B:

public class InheritedDict : Dictionary<string, string>
{
    public override void Add(string key, string value)
    {
        base.Add(key, value);
    }
}

另一个StackOverflow用户在解释我(在另一个帖子的评论中)解决方案A是正确的。这与我的想法相反。

显然这是因为“添加不是虚拟方法”。他指着我的文档(https://msdn.microsoft.com/en-us/library/k7z0zy8k(v=vs.110).aspx)。

我承认我仍然没有得到它。

编辑:所以问题是:为什么解决方案A会被视为错误代码? (对不起,当我错误地问“为什么解决方案 A 被视为不良代码?”时,@ Backs的答案才有意义。)

4 个答案:

答案 0 :(得分:4)

当您遮蔽方法时,如果客户端代码调用实例类型为基类的方法,则不会调用您的方法。它将调用基类方法。

这是您建议使用method1的主要原因。

例如:

Dictionary<string, string> dic = new InheritedDict();
dic.Add("key","value");//Will not call your method.

如果Add方法被声明为虚拟(它不是),则可以覆盖Add方法。在这种情况下,它将按预期调用派生类方法。

答案 1 :(得分:2)

短 - 没理由:) 我没有看到问题。您有自己的IDictionary实现。没关系。

答案 2 :(得分:2)

另一种可能性是扩展方法

  public static DictionaryExtensions {
    public static void MyAdd(this Dictionary<string, string> dictionary, String key, String value) {
      ...
    }
  } 

因此,您可以使用具有扩展功能的现有Dictionary<String, String>实现(Microsoft):

  Dictionary<string, string> dict = new Dictionary<string, string>();
  ...
  dict.MyAdd("myKey", "SomeValue");

答案 3 :(得分:2)

您可以将其视为每个实现的接口都有自己的虚拟方法表

仍然Dictionary.Add不是虚拟,您无法调用继承人的实施:

Dictionary<string, string> d = new InheritedDict<string, string>(); // Ok, you can do it
d.Add("foo", "bar"); // Wrong! You can, but Dictionary.Add will be called

可是:

public class InheritedDict : Dictionary<string, string>
{
    void IDictionary<string, string>.Add(string key, string value)
    {
        base.Add(key, value);
    }
}

Dictionary<string, string> d = new InheritedDict<string, string>();
var d2 = d as IDictionary<string, string>;
d2.Add("foo", "bar"); // Ok

第二种方式是困难的,对吧​​?

因此,它可以更好地实现整个接口IDictionary,而不是覆盖Dictionary的单个方法。因此,尽管解决方案A有点冗长,但它绝对正确。