可做笔记的阅读网站,建网站教程视频下载,金融审核网站制作,西安网站建设 早晨sizeof(T)从C的模板代码往C#代码移植的时候发现了一个小问题。在C模板代码中 sizeof(T)是一种有效的写法#xff0c;最终在会编译器展开成sizeof(int),sizeof(float)或者sizeof(myclass),然后在运行时这个代码是有效的#xff0c;能够执行的。于是我们看上去就可以计算在运行… sizeof(T)从C的模板代码往C#代码移植的时候发现了一个小问题。在C模板代码中 sizeof(T)是一种有效的写法最终在会编译器展开成sizeof(int),sizeof(float)或者sizeof(myclass),然后在运行时这个代码是有效的能够执行的。于是我们看上去就可以计算在运行时计算T的大小并分配内存。但是在C#的泛型代码中sizeof(T)无法编译过的因为无法确认T是什么的情况下T的大小是无法计算的于是C#编译器是不认的。按C#提供的规范sizeof只能在不安全的代码中使用操作的参数是非托管类型。# 非托管类型sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 或 bool任何枚举类型任何指针类型任何用户定义的 struct 类型只包含非托管类型的字段并且在 C# 7.3及更早版本中不是构造类型包含至少一个类型参数的类型那么在C#的泛型类里面该如何进行sizeof(T)操作然后我开始尝试着在.net的开源代码里面寻找答案OK,一下子找到两个Unsafe.SizeOf和Marshal.SizeOfUnsafe.SizeOfUnsafe.SizeOf 属于 CompilerServices继续挖掘代码最后得到了一段IL Code .method public hidebysig static int32 SizeOfT() cil managed aggressiveinlining { //.... .maxstack 1 sizeof !!T ret } // end of method Unsafe::SizeOfOK这是 IL语言我们就看自己关心的sizeof #IL Code 说明sizeof 将提供的值类型的大小以字节为单位推送到计算堆栈上。OK,UnsafeSizeOf只有值类型的大小Unsafe.SizeOfmyclass();不管我怎么改变myclass的内容结果都是8所以这个不能随便用只能用在值类型上了。结合C#的文档我蛮怀疑关键字sizeof要么是调用了Unsafe.Sizeof函数要么就是直接转换成了IL Code的sizeof。但没什么依据我没在.net的源代码里找到这一点。Marshal.SizeOf这个属于 System.Runtime.InteropServices是.net 和COM互操作的时候用的。这个函数挖掘代码之后是到了一些cpp代码基本路径是这样的Marshal.SizeOf-SizeOfHelper- MarshalNative::SizeOfClass-GetNativeSize()Marshal.SizeOf-SizeOfHelper是C#代码GetNativeSize()是用C代码实现的两边怎么焊接的我就不管了这个暂时不关心。最后 BOOL GetNativeSize() const { LIMITED_METHOD_CONTRACT; return m_cbNativeSize; }返回了一个m_cbNativeSize;OK,我们实际测试下Marshal.SizeOfmyclass();直接报错了因为不是一个非托管结构没法计算大小。Type ConsoleApp1.Programmyclass cannot be marshaled as an unmanaged structure; no meaningful sizeor offset can be computed.OK稍微调整下代码加一个[StructLayout(LayoutKind.Sequential)]然后输出结果是12刚好是三个int的大小。等下还有第三种办法从 C# 7.3 开始可使用 unmanaged 约束指定类型参数为“非指针、不可为 null 的非托管类型”。从 C# 8.0 开始仅包含非托管类型的字段的构造结构类型也是非托管类型如以下示例所示public struct CoordsT{ public T X; public T Y; } public class UnmanagedTypes { public static void Main() { DisplaySizeCoordsint(); DisplaySizeCoordsdouble(); } private unsafe static void DisplaySizeT() where T : unmanaged { Console.WriteLine(${typeof(T)} is unmanaged and its size is {sizeof(T)} bytes); } } // Output: // Coords1[System.Int32] is unmanaged and its size is 8 bytes // Coords1[System.Double] is unmanaged and its size is 16 bytes那么回到我开始的问题如果都是值类型两个都可以用如果是自定义类用Marshal.SizeOf就可以了或者把泛型类写成public struct CoordsT where T : unmanaged{ public T X; public T Y;}即T只限于非托管类型。结论1.值类型泛型类可以用where T : unmanaged 和sizeof(T)配合使用或者直接使用 Unsafe.Sizeof(T)2.非值类型泛型类可用Marshal.SizeOf(T)本文结束。 ------------------------------写在文后昨天发出之后发现把“泛”字打成范了想想还是删除了今天再发写一篇技术文章从选题写稿编辑检查错别字修改到发稿来来回回几个小时。没有一件事情是容易的。我尽量严肃对待这一切让各位关注者能有所得。谢谢。 ------------------------------写多不如写精 我是丁长老欢迎关注我的技术公众号。个人微信号nine-ding,欢迎加我微信。如需转发文章请加微信号获取转发授权