字典为什么能存储Key和Value呢?
其实内部存在一个结构:Entry
private struct Entry
{
public int hashCode; //key的hashCode
public int next; //解决hash冲突的
public TKey key;
public TValue value;
}
都有什么用呢?
可以看下 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].n
{
if (this.entries[index2].hashCode == num && this.comparer.Equals(this.entries[inde
{
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;
}
ps:使用字典的坑:
如果使用enum作为key,在遍历时会产生额外的GC。
其来源为:DefaultComparer.GetHashCode()
对于Enum类型,所产生的就是 ObjectEqualityComparer。
public override bool Equals(T x, T y)
{
if ((object) x != null)
{
if ((object) y != null)
return x.Equals((object) y);
return false;
}
return (object) y == null;
}
public override int GetHashCode(T obj)
{
if ((object) obj == null)
return 0;
return obj.GetHashCode();
}
而Enum,在IL代码里面是值类型,所以会造成装箱操作。
一个int为4字节,一个object为16字节,一次就有20B的GC。
GetHashCode一次,Equals一次,一共会有40B的GC。
解决方案:
自己实现一个Comparer
public Class EnumComparer : IEqualityComparer<TEnum>
{
public bool Equasl(TEnum x, TEnum y)
{
return (int)x == (int)y;
}
public intGetHashCode(TEnum obj)
{
return (int)obj;
}
}
注意:
TEnum,为对应的枚举类型。
无法使用模板类,因为编译不通过。(可以自己试一下)