首先看下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 ;
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 = ; 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 = ; i < fields.Length; i += ) {
object meVal = fields [i];
object youVal = fields [i + ];
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

Dictionary里使用struct,enum做key的更多相关文章

  1. C#中正确使用enum做Key的姿势

    C#中自定义enum,然后将其作为Dictionary的Key,通常的做法如下: using System; using System.Text; using System.Collections.G ...

  2. Unity3D研究之多语言用中文做KEY

     做多语言的时候用中文做KEY绝对是有100%的优点,假设用英文表示那么代码里面给文字赋值的地方全都是英文.写的代码多了以后维护起来就没有人能看懂了,或者看起来非常费劲. 对PoolManager ...

  3. React 等框架使用 index 做 key 的问题

    React 等框架使用 index 做 key 的问题 假如有两个树,一个是之前,一个是更变之后,我们抽象成两种可能性. 插入内容在最后 插入内容在最前 关于插在中间,原理一样,就不阐述. 使用 ul ...

  4. Go语言 判断key是否在map里 if _, ok := map[key]; ok

    if val, ok := map[key]; ok { //do something here } 如果key在map里 val 被赋值map[key] ok 是true 否则val得到相应类型的零 ...

  5. c++ struct enum union加typedef与不加typedef

    struct/enum/union加typedef与不加typedef 匿名结构体 struct { int a; int b; } v; // 这里表示定义了一个结构体的变量v,且结构体类型没有名字 ...

  6. 适当使用enum做数据字典 ( .net c# winform csharp asp.net webform )

    在一些应用中,通常会用到很多由一些常量来进行描述的状态数据,比如性别(男.女),审核(未审核.已审核)等.在数据库中一般用数字形式来存储,比如0.1等. 不好的做法 经常看到一些应用(ps:最近又看到 ...

  7. Dictionary通过Value找到它的key

    private void GetDicKeyByValue() { Dictionary<string, string> dic = new Dictionary<string, s ...

  8. Java学习笔记--HashMap中使用object做key的问题【转】

    在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...

  9. C# Dictionary通过value获取对应的key值

    1:最直白的循环遍历方法,可以分为遍历key--value键值对以及所有的key两种表现形式 2:用Linq的方式去查询(当然了这里要添加对应的命名空间 using System.Linq) 如下为一 ...

随机推荐

  1. [svc]几种访问google方案

    最近老被人问起,有什么访问谷歌的方法可以推荐. 针对小白用户(使用sass式即可) iass sass pass区别 小白可以用(无需安装软件,些许收费):googlegae: https://m.2 ...

  2. C++11时间操作

    C++11提供了chrono库,这个库可以处理和时间相关的一些事情.这个库里面主要有3个类:时间间隔Duration.时钟Clocks和时间点Time point. Duration template ...

  3. poj1703 Find them, Catch them(并查集的应用)

    Find them, Catch them   Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 32225   Accepte ...

  4. 【Objective-C】06-点语法

    前言 在Java中,我们可以通过"对象名.成员变量名"来访问对象的公共成员变量,这个就称为"点语法".比如: 1.在Student类的第2行定义了一个公共的成员 ...

  5. USART—串口通讯

    本章中主要讲解的是串口异步通讯,异步通讯中由于没有时钟信号, 所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码 . 串口通讯的一个数据包从起始信号开始,直到停止信号结束.数据 ...

  6. 基于ffmpeg 直播推流和播放rtmp (IOS源码)

    ios直播推流每秒能达到30帧,比安卓要强,视频采用软编码的话手机会发烫,得采用码编码,播放视频采用opengl渲染. ffmpeg初始化代码如下: int init_Code(int width, ...

  7. django 模板报错

    "Requested setting TEMPLATE_DEBUG, but settings are not configured. You must either define the ...

  8. Muller’s method (website)

    Muller's method: https://www.youtube.com/watch?v=3R8NY-trJwI :https://www.youtube.com/watch?v=p4vt7D ...

  9. 编写可维护的JavaScript----笔记(三)

    1.块语句花括号的使用 在JavaScript中,注入if和for语句有两种写法,使用花括号包裹的多行代码或者不使用花括号的单行代码.但强烈建议不论是单行还是多行代码,都应该使用花括号. 2.花括号的 ...

  10. 消息队列ipc的一些设置

    Linux IPC 参数设定- 命令方式: echo 80 > /proc/sys/vm/overcommit_ratio, etc MSGMNB 每个消息队列的最大字节限制. MSGMNI 整 ...