Dictionary字典相关

本文探讨了字典内部的Entry结构,用于存储Key-Value对,并解析了Insert方法的工作原理,包括解决哈希冲突和更新已有键值对。此外,还揭示了使用枚举作为字典键可能导致的额外GC开销,原因是默认比较器导致的装箱操作。为避免此问题,建议自定义EnumComparer来提高性能。
摘要由CSDN通过智能技术生成

字典为什么能存储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,为对应的枚举类型。
无法使用模板类,因为编译不通过。(可以自己试一下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值