【问题标题】:Modifying Add in Dictionary: reimplement IDictionary vs inheriting from Dictionary修改字典中的添加:重新实现 IDictionary 与从字典继承
【发布时间】:2015-08-07 10:05:36
【问题描述】:

假设我需要在我的Dictionary<string, string> 中重新定义Add

解决方案 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 用户告诉我(在另一个线程的 cmets 部分)解决方案 A 是正确的。这与我的预期相反。

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

我承认我还是不明白。

编辑:所以问题是:为什么解决方案 B 会被认为是坏代码? (抱歉,当我错误地问“为什么解决方案 A 会被视为错误代码?”时,@Backs 的回答是有道理的)

【问题讨论】:

  • 还有什么问题?
  • @Backs 抱歉,在帖子中编辑:“所以问题是:为什么解决方案 A 会被视为错误代码?”
  • 我相信你会在那篇文章中得到答案。您能否分享指向您所指的 StackOverflow 问题的链接
  • @SriramSakthivel 帖子链接是 stackoverflow.com/questions/31873149/… ,cmets 在 MatíasFidemraizer 的回答下。
  • 解决方案 B 甚至无法编译,因为正如您所指出的,Add 不是虚拟的。

标签: c#


【解决方案1】:

当你隐藏一个方法时,如果客户端代码调用该方法的实例类型为基类,那么你的方法将不会被调用。它将调用基类方法。

这是建议您使用方法1的主要原因。

例如:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      还有一种可能是扩展方法

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

      因此您可以使用现有的Dictionary&lt;String, String&gt; 实现(Microsoft)和扩展功能:

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

      【讨论】:

        【解决方案4】:

        你可以把它想象成每个实现的接口都有自己的虚方法表

        仍然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虽然有点冗长,但绝对正确。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-08
          • 1970-01-01
          • 2017-12-17
          • 2018-02-09
          • 1970-01-01
          相关资源
          最近更新 更多