Dictionary里使用struct,enum做key

首先看下Dictionary的源码

public void Add (TKey key, TValue value)
		{
			if (key == null)
				throw new ArgumentNullException ("key");

			// get first item of linked list corresponding to given key
			int hashCode = hcp.GetHashCode (key) | HASH_FLAG;
			int index = (hashCode & int.MaxValue) % table.Length;
			int cur = table [index] - 1;

			// walk linked list until end is reached (throw an exception if a
			// existing slot is found having an equivalent key)
			while (cur != NO_SLOT) {
				// The ordering is important for compatibility with MS and strange
				// Object.Equals () implementations
				if (linkSlots [cur].HashCode == hashCode && hcp.Equals (keySlots [cur], key))
					throw new ArgumentException ("An element with the same key already exists in the dictionary.");
				cur = linkSlots [cur].Next;
			}

			if (++count > threshold) {
				Resize ();
				index = (hashCode & int.MaxValue) % table.Length;
			}
			
			// find an empty slot
			cur = emptySlot;
			if (cur == NO_SLOT)
				cur = touchedSlots++;
			else 
				emptySlot = linkSlots [cur].Next;

			// store the hash code of the added item,
			// prepend the added item to its linked list,
			// update the hash table
			linkSlots [cur].HashCode = hashCode;
			linkSlots [cur].Next = table [index] - 1;
			table [index] = cur + 1;

			// store item's data 
			keySlots [cur] = key;
			valueSlots [cur] = value;

			generation++;
		}

  

int hashCode = hcp.GetHashCode (key) | HASH_FLAG;

hcp

[Serializable]
        sealed class DefaultComparer : EqualityComparer<T> {
    
            public override int GetHashCode (T obj)
            {
                if (obj == null)
                    return 0;
                return obj.GetHashCode ();
            }
    
            public override bool Equals (T x, T y)
            {
                if (x == null)
                    return y == null;
                
                return x.Equals (y);
            }
        }

其实就是走到obj.GetHashCode,如果obj.GetHashCode没有覆盖的话,那就会走到ValueType的GetHashCode

public override int GetHashCode ()
        {
            object[] fields;
            int result = InternalGetHashCode (this, out fields);

            if (fields != null)
                for (int i = 0; i < fields.Length; ++i)
                    if (fields [i] != null)
                        result ^= fields [i].GetHashCode ();
                
            return result;
        }

注意看

[MethodImplAttribute (MethodImplOptions.InternalCall)]
        internal extern static int InternalGetHashCode (object o, out object[] fields);
int result = InternalGetHashCode (this, out fields);
会把this转成object类型,第1次boxing,而且会把每个字段都转成object,放入fields里,所以会有多次gc alloc
这个是不重载GetHashCode导致的gc alloc。
下一个是
if (linkSlots [cur].HashCode == hashCode && hcp.Equals (keySlots [cur], key))

hcp.Equals

如果T没有实现IEquatable,就会走到DefaultCOmparer,然后会走到

这个Equals会调用ValueType.Equals

internal static bool DefaultEquals (object o1, object o2)
        {
            object[] fields;

            if (o2 == null)
                return false;

            bool res = InternalEquals (o1, o2, out fields);
            if (fields == null)
                return res;

            for (int i = 0; i < fields.Length; i += 2) {
                object meVal = fields [i];
                object youVal = fields [i + 1];
                if (meVal == null) {
                    if (youVal == null)
                        continue;

                    return false;
                }

                if (!meVal.Equals (youVal))
                    return false;
            }

            return true;
        }

        // <summary>
        //   True if this instance and o represent the same type
        //   and have the same value.
        // </summary>
        public override bool Equals (object obj)
        {
            return DefaultEquals (this, obj);
        }

这个里面会把x,y都转成object.所以会有2次boxing

至此所有的boxing都清楚了,工程例子在

https://github.com/yingsz/DictionaryAlloc

消除boxing参考

http://www.bkjia.com/Asp_Netjc/1314145.html

转载于:https://www.cnblogs.com/marcher/p/10150622.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值