型网站建设,广州市外贸网站建设服务机构,新手学做网站这本书,支持wordpress免费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{.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() ( 01 00 00 00 ).maxstack 1sizeof !!Tret} // end of method Unsafe::SizeOfOK这是 IL语言我们就看自己关心的sizeof #IL Code 说明sizeof 将提供的值类型的大小以字节为单位推送到计算堆栈上。OK,UnsafeSizeOf 只有值类型的大小Console.WriteLine(Unsafe.SizeOfmyclass().ToString());不管我怎么改变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,我们实际测试下Console.WriteLine(Marshal.SizeOfmyclass().ToString());直接报错了因为不是一个非托管结构没法计算大小。Type ConsoleApp1.Programmyclass cannot be marshaled as
an unmanaged structure; no meaningful size or 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.非值类型范型类可用[StructLayout(LayoutKind.Sequential)] 和Marshal.SizeOf(T)配合使用本文结束。