C#(含Unity)unsafe指针快速反射第四篇(整合篇 )

2025-12-13 0 700

Unity3D(已完成iL2cpp和Mono的编译)请访问:smopu/unity3d_quick_reflection: 在unity3D中使用指针进行快速反射 (github.com)

.Net Framework 和.Net Core请访问:smopu/CSharp_QuickReflection: C# .Net Framework Quick Reflection 快速反射 (github.com)

整合的解决方案已经放在上面地址中了。其中Unity通过IL2Cpp编译,保证在AOP的情况下,能顺利使用(包括iOS平台、WebGL平台)

这篇文章就简单介绍一下上面解决方案的基本内容。

看到前面三篇文章的读者大部分都是Unity使用者哈,其实本人也是unity开发者之一,之所以还研究.Net Framework 和.Net Core是因为以下三个原因:

1、本人先学的.Net Framework后学的Unity,所以概念先入为主了。

2、据不可靠消息称,Unity将在2024年支持.Net Core。

3、鉴于Unity对中国开发者的各种区别对待,本人随时保持脱离该引擎的准备,但大概率不会脱离C#这门语言,所以支持的内容必须保证.Net Framework 和.Net Core。

看读者评论不多,估计一些基本概念本人还没有讲清楚。实际上使用C#,很多情况下不会使用指针,但是大部分框架都会用到反射,C#、Java的各种框架和解决方案中,反射都是很基础的功能,尤其是涉及到面向切面编程(Aspect Oriented Programming,缩写为:AOP)、控制反转(Inversion of Control,缩写为IoC)的概念。

指针的基础用法就是两个:取地址和取指针的值

取地址:

int a = 1; int* p = &a; 

取指针的值:

int a = *p; 

然后指针可以强制转换,我们可以把int类型的指针当作float类型取值:

int a = 1; int* p = &a; float b = *(float*)p; 

我们通过反编译看float在C#中的源代码,看GetHashCode这个函数就能发现这样的操作

C#(含Unity)unsafe指针快速反射第四篇(整合篇 )

Single.GetHashCod()源代码

Single.GetHashCod()的作用就是把float类型转换成一个int类型 ,转换方法就是把float类型中的数据,当作int类型取一遍。学习过计算机理论课程的朋友肯定知道IEEE浮点数的概念,本人也有一篇文章:

流觞曲水醉江蛟:C#浮点数
比如float数字6.4的二进制代码是 01000000110011001100110011001101,我们把这一段代码当作整数读取就是1087163597。以下代码就能看出来

float a = 6.4f; int b = *(int*)(&a);//1087163597  int b2 = a.GetHashCode();//1087163597 

在C#中,引用类型的对象(包括包装类)会有一个类型指针的内容在对象最开始。

比如这样的类:

public class G { public int a = 12; public string b = \"1sdjfoisdjf\"; public Vector3 c = new Vector3(1.1f, 2.2f, 3.3f); } 

这样的对象在内存中它是这样的

C#(含Unity)unsafe指针快速反射第四篇(整合篇 )

在C#中,关于引用类型的指针,统一是void*,无论它是什么类型。比如b字段是字符串类型,但是它的指针还是void*而不是string*。同样的,在IL语言中,void*就是Object类型,它们的区别在于,Object类型会随着GC改变内存地址(分代GC),但是Unity用的是mono(IL2cpp在内存概念上跟Mono一致),没有分代GC,所以对象地址不会改变。因此在Unity中,void*和Object完全一致。

而IntPtr代表所有指针,是所有指针的元类型。

解决分代GC的问题我们在第二篇已经提到过了,这里不多说了。

在.Net系统库中,原生的反射(System.Reflection),会区分字段和属性,本人这个解决方案把这两个合并在一起。可以看我工程里面的TypeAddrFieldAndProperty.cs文件。

因为合并在一起,所以处理时,还是会判断一下:

C#(含Unity)unsafe指针快速反射第四篇(整合篇 )

上面说过了void*等同于object,以下代码就能实现对原生反射的平替。

C#(含Unity)unsafe指针快速反射第四篇(整合篇 )

GetValue也是一样的啦。

当分析一个类的时候,我把一个类型的所有字段和属性全部取出,把各种需要的内容(偏移量、是否值类型(否就是引用类型)、当前字段或者属性的类型等)缓存,详见TypeAddrReflectionWrapper类。

数组需要单独处理一下,详见ArrayWrapManager.cs,我用了一个基类IArrayWrap,继承这个基类的类型就两个,一个是1维数组的类(ArrayWrapRankOne),另一个是多维数组的类(ArrayWrapRank)。

主要内容在第三篇讲解了,我们使用指针反射可以反射任意维度的数组。关于多维数组的内容还可以看我另一篇文章:流觞曲水醉江蛟:C#反射序列化多维数组

接下来还有一篇性能比较的文章,我将比较指针反射和原生反射、Emit技术、表达式树技术之间的性能。还请广大读者多提意见。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 C#(含Unity)unsafe指针快速反射第四篇(整合篇 ) https://www.zuozi.net/36444.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务