通过源代码分析C#Dictionary的关键实现

1.Dictionary的Add实现。

   在Dictionary内部有几个关键字段,他们是理解Dictionary的关键。这些关键字段如下:

   private int[] buckets;

   private Dictionary.Entry[] entries;

   private IEqualityComparer compare

这几个字段的用途稍后讲解。

接下来看一下Add方法的实现,如下:

   public void Add(TKey key, TValue value)
    {
      this.Insert(key, value, true);
    }
可知,Add方法调用了一个Insert方法,转到Insert的内部实现如下:

private void Insert(TKey key, TValue value, bool add)
    {
      if ((object) key == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
      if (this.buckets == null)
        this.Initialize(0);
      int num = this.comparer.GetHashCode(key) & int.MaxValue;
      int index1 = num % this.buckets.Length;
      for (int index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next)
      {
        if (this.entries[index2].hashCode == num && this.comparer.Equals(this.entries[index2].key, key))
        {
          if (add)
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
          this.entries[index2].value = value;
          ++this.version;
          return;
        }
      }
      int index3;
      if (this.freeCount > 0)
      {
        index3 = this.freeList;
        this.freeList = this.entries[index3].next;
        --this.freeCount;
      }
      else
      {
        if (this.count == this.entries.Length)
        {
          this.Resize();
          index1 = num % this.buckets.Length;
        }
        index3 = this.count;
        ++this.count;
      }
      this.entries[index3].hashCode = num;
      this.entries[index3].next = this.buckets[index1];
      this.entries[index3].key = key;
      this.entries[index3].value = value;
      this.buckets[index1] = index3;
      ++this.version;
    }

这段代码有点长,但只要静下心来很容易看懂。有些不重要的代码暂且不论,分析如下:

1.首先判断,key是否为null,如果为null就抛出一个ArgumentNullException异常。

2.使用IEqualityComparer来获取关键字key的哈希值,然后于int的最大值做与运算,将结果赋值给num。代码如下:

 int num = this.comparer.GetHashCode(key) & int.MaxValue;

3.将num于bucketes.Length做模运算,结果是一个小于length的值,这样这个值就可以索引bucketes了。

int index1 = num % this.buckets.Length;

4.判断bucketes中是否有要插入的关键字了,这是通过一个for循环来实现的。



你可能感兴趣的:(通过源代码分析C#Dictionary的关键实现)