当前位置: 首页 > news >正文

C#笔记啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

各数据类型的字节数

byte、sbyte、bool、char1
short、ushort2
int、uint、float4
long、ulong、double8
string(栈内存的引用地址)32位4,64位8

反射总结

得到Type

typeof(类名);
实例.GetType();
Type.GetType("命名空间.类名");

得到公共成员

MemberInfo memberInfos[]=type.GetMembers();

得到构造函数

得到所有:

ConstructorInfo[] constructorInfos=type.GetConstructors();

得到无参:

ConstructorInfo constructorInfo=type.GetConstructor(new Type[0]);
MyClass myClass=constructorInfo.Invoke(null) as MyClass;

得到有参:

ConstructorInfo constructorInfo2=type.GetConstructor(new Type[]{typeof(参数类型)});
myClass=constructorInfo2.Invoke(new object[]{2}) as MyClass;

Activator快速实例化

myClass=Activator.CreateInstance(type) as MyClass;

得到公共字段

按字段名得到:

FieldInfo fieldInfo=type.GetField(string 字段名);

得到所有字段

FieldInfo[] fieldInfos=type.GetFields();

公共字段读写

fieldInfo.GetValue(实例);
fieldInfo.SetValue(实例,数据);

得到公共方法

得到所有

MethodInfo[] methodInfos=type.GetMethods();

按方法名得到:

MethodInfo methodInfo=type.GetMethod(string 方法名,new Type[]{typeof(参数1类型),...});

执行公共方法

实例方法

methodInfo.Invoke(实例,new object[]{参数1,...});

静态方法

methodInfo.Invoke(null,new object[]{参数1,...});

获得List的Fields,什么都没得到

List<int>data=new List<int>(){123,14,4234};
Type dataType=data.GetType();
FieldInfo[] fieldInfos=dataType.GetFields();

正确用法:把List装到一个class里。

deepseek回答字典的底层机制

C# 的 Dictionary<TKey, TValue> 使用 ‌链地址法(Chaining)‌ 的改良实现来解决哈希冲突,这是一种基于数组索引的虚拟链表结构而非物理离散节点24。其核心设计融合了数组的连续存储优势和链表的冲突处理能力,具体实现如下:


一、底层数据结构与冲突解决机制

  1. 双数组结构

    • buckets[] 数组‌:存储桶的头节点索引(指向 entries[] 的位置),初始值为 -1 表示空桶45。
    • entries[] 数组‌:连续存储键值对(Entry 结构体),每个 Entry 包含:
      struct Entry {public int hashCode; // 哈希码(低31位)public int next;     // 冲突链的下一个节点索引(-1 表示结尾)public TKey key;public TValue value;
      }
      
      通过 next 字段形成逻辑链表,解决哈希冲突45。
  2. 冲突处理流程
    当插入键值对时:

    • 计算键的哈希值 hashCode,映射到 buckets 数组的索引 bucketIndex45。

    • 若 buckets[bucketIndex] 为 -1,直接存入 entries[] 的新位置。

    • 若发生冲突(buckets[bucketIndex] 非 -1),将新 Entry 的 next 指向当前桶的头节点,并更新 buckets[bucketIndex] 为新节点的索引67。
      本质是通过 next 字段在连续数组内模拟链表操作‌,而非动态分配离散节点46。


二、为何未采用开放地址法(Open Addressing)

  1. 内存与性能权衡

    • 开放地址法要求所有数据存储在单一连续数组,扩容时需全量迁移,代价高昂810。
    • 链地址法通过逻辑链表分离冲突数据,扩容仅需重建 buckets 索引,entries 数组可部分复用610。
  2. 删除操作高效性

    • 开放地址法删除需标记“墓碑”位置,导致查找路径变长10。
    • 链地址法直接修改 next 指针即可删除节点,无需特殊标记910。
  3. 高装载因子容忍度

    • 当装载因子 >1 时(如数据量远超桶数量),链地址法仅延长链表长度,而开放地址法性能会急剧退化810。
    • C# Dictionary 默认装载因子为 0.72,超过时触发扩容56。

三、改良链地址法的优势

  1. 缓存友好性
    entries[] 数组连续存储,相比物理链表减少内存碎片,提升 CPU 缓存命中率47。
  2. 预分配与复用
    初始化时预分配 entries[],删除节点时通过 freeList 链表复用空位,减少内存分配开销67。

总结对比

特性C# 字典的链地址法改良传统开放地址法
冲突解决数组内虚拟链表 (next 索引链) 47线性/二次探测空槽 310
内存连续性键值对在 entries[] 中连续存储 4所有数据在单一数组连续存储 10
删除效率直接修改索引链,高效 69需标记墓碑,影响查找 10
高负载因子适应性链表长度增加,性能线性下降 10性能急剧退化 810

因此,C# Dictionary 通过‌数组化链地址法‌,在内存效率、冲突处理与动态扩容间取得了平衡4

追问:这么看来buckets数组是一个整数数组?

是的,C# 的 Dictionary<TKey, TValue> 中的 buckets 数组是一个‌整数数组(int[]‌,其核心作用是通过存储索引值来关联哈希桶与键值对数据。具体实现细节如下:


一、buckets 数组的结构与功能

  1. 数据类型与用途

    • buckets 数组的每个元素是 int 类型,存储的是 entries 数组的索引值(即键值对在 entries 中的位置)15。
    • 初始化时,buckets 的所有元素默认值为 -1,表示空桶5。
  2. 哈希映射流程

    • 当插入或查找键值对时,哈希函数计算键的哈希值,并通过取模运算映射到 buckets 的某个索引 bucketIndex46。
    • 若 buckets[bucketIndex] 为 -1,表示无冲突,直接存入 entries;否则通过 next 字段形成逻辑链表解决冲突15。

二、buckets 与 entries 的协同关系

  1. entries 数组的存储

    • entries 是 Entry 结构体数组,包含 hashCodenextkey 和 value 字段5。
    • next 字段指向同一哈希桶中的下一个 Entry 索引(类似链表指针),形成冲突链16。
  2. 内存布局示例

    textCopy Code

    buckets = [ -1, 2, -1, 0 ] // 桶索引 3 指向 entries[0] entries = [ { hashCode=123, next=1, key="K1", value="V1" }, // 冲突链头 { hashCode=123, next=-1, key="K2", value="V2" } // 冲突链尾 ]


三、设计优势与性能考量

  1. 高效的内存利用
    • 整数数组 buckets 占用空间小,且通过 entries 的连续存储减少内存碎片45。
  2. 快速冲突解决
    • 逻辑链表(通过 next 索引)比物理链表(如 LinkedList)更缓存友好,减少指针跳转开销14。

总结

  • buckets 是 int[] 类型,核心功能是通过索引关联哈希桶与 entries 中的键值对15。
  • 这种设计结合了数组的连续性和链表的冲突处理能力,兼顾了哈希表的高效查找与动态扩展需求

人话总结

字典有2个数组:整数数组buckets,结构体数组entries,哈希冲突的键会得到同一个bucketsIndex,buckets的值是这些哈希冲突的键值对中的第一个在entries的索引,通过entry结构体的next找到下一个键值对索引,直到找到next==-1的也就是最后一个键值对,把新键值对加入entries最后,next==-1的键值对next改成新加入的键值对索引。

如果某个bucketsIndex下的值是-1,则直接加入entries最后,buckets[bucketsIndex]改成这个新加的索引。

键值对在内存是连续、乱序的。

http://www.lryc.cn/news/621392.html

相关文章:

  • JavaScript 解构赋值语法详解
  • 开源卫星软件平台LibreCube技术深度解析
  • DAY 42 Grad-CAM与Hook函数
  • 一文讲透Go语言并发模型
  • PHP现代化全栈开发:实时应用与WebSockets实践
  • PIDGenRc函数中lpstrRpc的由来和InitializePidVariables函数的关系
  • 技术速递|通过 GitHub Models 在 Actions 中实现项目自动化
  • 状态管理、网络句柄、功能组和功能组状态的逻辑关系
  • 提升工作效率的利器:GitHub Actions Checkout V5
  • 【力扣56】合并区间
  • Linux软件编程(四)多任务与多进程管理
  • CMake进阶: externalproject_add用于在构建阶段下载、配置、构建和安装外部项目
  • Google Gemini 的深度研究终于进入 API 阶段
  • 入门概述(面试常问)
  • CodeTop 复习
  • C#WPF实战出真汁01--项目介绍
  • C++入门自学Day11-- List类型的自实现
  • Claude Code频繁出错怎么办?深入架构层面的故障排除指南
  • 力扣-5.最长回文子串
  • Python3 详解:从基础到进阶的完整指南
  • RS232串行线是什么?
  • 机器学习-支持向量机器(SVM)
  • 机器学习——TF-IDF算法
  • 2025天府杯数学建模A题分析
  • Docker存储卷备份策略于VPS服务器环境的实施标准与恢复测试
  • 【ai写代码】lua-判断表是否被修改
  • 【JDK】Linux 系统下 JDK 安装与环境变量配置全教程
  • Auto-Coder的CLI 和 Python API
  • TOTP算法与HOTP算法
  • 下标访问操作符 [] 与函数调用操作符 ()