Dictionary.Clear和 new Dictionary()有什么不同?

咨询区

  • Newbie

请问 Dictionary.Clear() 和 new Dictionary() 到底有什么不同,哪一种在实际开发中更为推荐?.

回答区

  • Reed Copsey

Dictionary.Clear() 方法会移除 Dictionary 中的所有 keyvalue 项,对应到内部就是 _bukects 和 _entries 数组,可以从源码中看的最清楚。

        public void Clear()
        {
            int count = _count;
            if (count > 0)
            {
                Array.Clear(_buckets, 0, _buckets.Length);
                _count = 0;
                _freeList = -1;
                _freeCount = 0;
                Array.Clear(_entries, 0, count);
            }
        }

而 new Dictionary() 会在托管堆上创建一个 dictionary 的一个实例。

0:000> !dumpheap -stat
Statistics:
      MT    Count    TotalSize Class Name
63936278        1           48 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.Int32, mscorlib]]

编程实践中,他们大多可以实现相同的效果,主要取决你是否需要保留原 Dictionary,也就是 this 。

void NewDictionary(Dictionary<string,int> dict)
{
   dict = new Dictionary<string,int>(); // Just changes the local reference
}

void  ClearDictionary(Dictionary<string,int> dict)
{
   dict.Clear();
}

// When you use this...
Dictionary<string,int> myDictionary = ...; // Set up and fill dictionary

NewDictionary(myDictionary);
// myDictionary is unchanged here, since we made a new copy, but didn't change the original instance

ClearDictionary(myDictionary);
// myDictionary is now empty

  • Brian Gideon

Dictionary.Clear 会移除 Dictionary 中的所有项,而 new Dictionary() 会生成一个新实例,而这个新实例刚好也就是空状态,不过他们还是有一些细微的差别,考虑如下代码:

void Example1()
{
  var collection = new Dictionary<string, string>();
  collection.Add("key1", "value1");
  collection.Add("key2", "value2");
  foreach (var kvp in collection)
  {
    collection = new Dictionary<string, string>();
    Console.WriteLine(kvp);
  }
}

void Example2()
{
  var collection = new Dictionary<string, string>();
  collection.Add("key1", "value1");
  collection.Add("key2", "value2");
  foreach (var kvp in collection)
  {
    collection.Clear();
    Console.WriteLine(kvp);
  }
}

第一个例子中 foreach 会打印出所有的 collection 内容,第二个例子会抛出 InvalidOperationException 异常,这是因为犯了 迭代时修改 异常。

点评区

其实我个人建议使用 Dictionary.Clear(), 因为它不会给 GC 造成多大的负担,而你每次的 new 操作容易在 heap 上产生太多的垃圾数据。