1.Dictionary的Add实现。
在Dictionary内部有几个关键字段,他们是理解Dictionary的关键。这些关键字段如下:
private int[] buckets;
private Dictionary<TKey, TValue>.Entry[] entries;
private IEqualityComparer<TKey> 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循环来实现的。