C#Dictionary接口源码分析

 1.Dictionary   主要对象 Entry[]

private Dictionary.Entry[] entries;
using System;

// Token: 0x02000BA6 RID: 2982
private struct Entry
{
	// Token: 0x040034EC RID: 13548
	public int hashCode;

	// Token: 0x040034ED RID: 13549
	public int next;

	// Token: 0x040034EE RID: 13550
	public TKey key;

	// Token: 0x040034EF RID: 13551
	public TValue value;
}

 2.内存管理,HashHelpers.primes 一组已定义的集合大小数组。

 public static int GetPrime(int min)
{
	if (min < 0)
	{
		throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
	}
	for (int i = 0; i < HashHelpers.primes.Length; i++)
	{
		int num = HashHelpers.primes[i];
		if (num >= min)
		{
			return num;
		}
	}
	for (int j = min | 1; j < 2147483647; j += 2)
	{
		if (HashHelpers.IsPrime(j) && (j - 1) % 101 != 0)
		{
			return j;
		}
	}
	return min;
}

3.buckets、Entry(集合)数组的初始化 (buckets哈希表)、(capacity容量)

// System.Collections.Generic.Dictionary
// Token: 0x06003921 RID: 14625 RVA: 0x000D97B8 File Offset: 0x000D79B8
private void Initialize(int capacity)
{
	int prime = HashHelpers.GetPrime(capacity);
	this.buckets = new int[prime];
	for (int i = 0; i < this.buckets.Length; i++)
	{
		this.buckets[i] = -1;
	}
	this.entries = new Dictionary.Entry[prime];
	this.freeList = -1;
}

4.IDictionary接口

using System;

namespace System.Collections.Generic
{
	// Token: 0x020004A5 RID: 1189
	[__DynamicallyInvokable]
	public interface IDictionary : ICollection>, IEnumerable>, IEnumerable
	{
		// Token: 0x170008CC RID: 2252
		[__DynamicallyInvokable]
		TValue this[TKey key]
		{
			[__DynamicallyInvokable]
			get;
			[__DynamicallyInvokable]
			set;
		}

		// Token: 0x170008CD RID: 2253
		// (get) Token: 0x06003998 RID: 14744
		[__DynamicallyInvokable]
		ICollection Keys { [__DynamicallyInvokable] get; }

		// Token: 0x170008CE RID: 2254
		// (get) Token: 0x06003999 RID: 14745
		[__DynamicallyInvokable]
		ICollection Values { [__DynamicallyInvokable] get; }

		// Token: 0x0600399A RID: 14746
		[__DynamicallyInvokable]
		bool ContainsKey(TKey key);

		// Token: 0x0600399B RID: 14747
		[__DynamicallyInvokable]
		void Add(TKey key, TValue value);

		// Token: 0x0600399C RID: 14748
		[__DynamicallyInvokable]
		bool Remove(TKey key);

		// Token: 0x0600399D RID: 14749
		[__DynamicallyInvokable]
		bool TryGetValue(TKey key, out TValue value);
	}
}

5.函数实现添加

// System.Collections.Generic.Dictionary
// Token: 0x06003922 RID: 14626 RVA: 0x000D9808 File Offset: 0x000D7A08
private void Insert(TKey key, TValue value, bool add)
{
	if (key == null)
	{
		ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
	}
	if (this.buckets == null)
	{
		this.Initialize(0);
	}
	int num = this.comparer.GetHashCode(key) & int.MaxValue;
	int num2 = num % this.buckets.Length;
	int num3 = 0;
	for (int i = this.buckets[num2]; i >= 0; i = this.entries[i].next)
	{
		if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key))
		{
			if (add)
			{
				ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
			}
			this.entries[i].value = value;
			this.version++;
			return;
		}
		num3++;
	}
	int num4;
	if (this.freeCount > 0)
	{
		num4 = this.freeList;
		this.freeList = this.entries[num4].next;
		this.freeCount--;
	}
	else
	{
		if (this.count == this.entries.Length)
		{
			this.Resize();
			num2 = num % this.buckets.Length;
		}
		num4 = this.count;
		this.count++;
	}
	this.entries[num4].hashCode = num;
	this.entries[num4].next = this.buckets[num2];
	this.entries[num4].key = key;
	this.entries[num4].value = value;
	this.buckets[num2] = num4;
	this.version++;
	if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(this.comparer))
	{
		this.comparer = (IEqualityComparer)HashHelpers.GetRandomizedEqualityComparer(this.comparer);
		this.Resize(this.entries.Length, true);
	}
}

哈希表,这个算法太厉害了,很佩服微软大神,先说哈希表这个机制的作用

1.查询速度会非常快,数据的多少不影响查询速度

我们分2种情况来讨论这个

1.一张表记录数据在集合的位置的表,表是素数个数,方便数据地址分配这个表中(现在表的大小3)

2.集合

 

1.不冲突

key的GethashCode()mod表的大小,在这个表余数是0,在表0的位置中没有放内存为-1,判断是否大于0,直接放数据地址,查询的时候,余数0,直接取表的数据地址,比对哈希表的值,再比对对象是是否一致。

2.冲突

同样余数0,在表0的位置存数据地址,发现表0地址大于0等于0,那问题就来了,说明已经存数据地址,怎么办,微软大神,用链接法,继续存数据地址,但是把之前的地址复制给数据中next,这时候查询是从表中取出的地址与key的哈希表对比值,如果相等,就比较key的值。

  其他的接口下次补充

 

 

 

 

 

 

 

   

 

 

 

你可能感兴趣的:(编程)