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 ;
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的更多相关文章
- C#中正确使用enum做Key的姿势
C#中自定义enum,然后将其作为Dictionary的Key,通常的做法如下: using System; using System.Text; using System.Collections.G ...
- Unity3D研究之多语言用中文做KEY
做多语言的时候用中文做KEY绝对是有100%的优点,假设用英文表示那么代码里面给文字赋值的地方全都是英文.写的代码多了以后维护起来就没有人能看懂了,或者看起来非常费劲. 对PoolManager ...
- React 等框架使用 index 做 key 的问题
React 等框架使用 index 做 key 的问题 假如有两个树,一个是之前,一个是更变之后,我们抽象成两种可能性. 插入内容在最后 插入内容在最前 关于插在中间,原理一样,就不阐述. 使用 ul ...
- 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得到相应类型的零 ...
- c++ struct enum union加typedef与不加typedef
struct/enum/union加typedef与不加typedef 匿名结构体 struct { int a; int b; } v; // 这里表示定义了一个结构体的变量v,且结构体类型没有名字 ...
- 适当使用enum做数据字典 ( .net c# winform csharp asp.net webform )
在一些应用中,通常会用到很多由一些常量来进行描述的状态数据,比如性别(男.女),审核(未审核.已审核)等.在数据库中一般用数字形式来存储,比如0.1等. 不好的做法 经常看到一些应用(ps:最近又看到 ...
- Dictionary通过Value找到它的key
private void GetDicKeyByValue() { Dictionary<string, string> dic = new Dictionary<string, s ...
- Java学习笔记--HashMap中使用object做key的问题【转】
在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...
- C# Dictionary通过value获取对应的key值
1:最直白的循环遍历方法,可以分为遍历key--value键值对以及所有的key两种表现形式 2:用Linq的方式去查询(当然了这里要添加对应的命名空间 using System.Linq) 如下为一 ...
随机推荐
- atitit.流程标准化--- mysql启动不起来的排查流程attilax总结
atitit.流程标准化--- mysql启动不起来的排查流程attilax总结 1. mysql的启动日志文件 1 2. console方式 1 3. 安装为服务 1 3.1. 使用默认配置文件 1 ...
- C# 使用IP端口网络打印图片
/// <summary> /// POSPrinter的摘要说明. /// 此类处理网络打印,使用了IP端口. /// </summary> public class Net ...
- 5.3日,7:20开始 阮一峰js的早课学习
Infinity - Infinity // NaN Infinity / Infinity // NaN Infinity + Infinity // Infinity Infinity * Inf ...
- httpclient 优化
(1)采用单例模式(重用HttpClient实例) 对于一个通信单元甚至是整个应用程序,Apache强烈推荐只使用一个HttpClient的实例.例如: private static HttpC ...
- java 读写文件常用方法
package study.bigdata; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; ...
- 玩转Win10的45个快捷键
1Win10快捷键大全(第一部分) Win10发布已经快两个星期了,各项新功能也让小伙伴们兴奋不已.和之前系统一样,Win10也加入了很多经典的快捷键,同时还加入了全新触控手势.今天小编就将所有的Wi ...
- Oracle 计算两个时间的差值
有两个日期数据START_DATE,END_DATE,欲得到这两个日期的时间差(以天,小时,分钟,秒,毫秒):天:ROUND(TO_NUMBER(END_DATE - START_DATE))小时:R ...
- SSH框架-Struts2基础-Action
Struts2的目录结构: 解压apps目录下的struts2-blank.war: 仿照这个最基本的项目,拷贝相关文件: 1.拷贝apps/struts2-blank/WEB-INF/classes ...
- 鼠标滑入滑出,输入框获得失去焦点后触发事件的N种方法之一二
熟悉position的用法 <!doctype html><html lang="en"> <head> <meta charset=&q ...
- iOS -转载-开发之个人开发者账号转公司开发者账号
ps : 个人开发者账号升级公司开发者账号的话需要账号开启双重认证,没有开启的话需要开启(不然走到可以升级的那步的话,点击update升级会提示为了安全起见需要账号开启双双重认证,反正我走到upd ...