C# 获取对象 大小 Marshal.SizeOf (sizeof 只能在不安全的上下文中使用)

本文探讨了C#中如何获取对象占用内存的大小,指出sizeof运算符仅适用于值类型且在不安全上下文使用,而Marshal.SizeOf适用于引用类型和值类型。对于托管对象,无法直接获取内存大小,而对于非托管对象和内置类型,可以使用相应方法进行计算。同时,文章提到使用二进制序列化得到的内存大小并不准确。
摘要由CSDN通过智能技术生成

C# 能否获取一个对象所占内存的大小?
今日,在项目重构的时候忽然想到一个问题,一个类哪些成员的增加,会影响一个类所占内存的大小?C#有没有办法知道一个对象占多少内存呢?

 第一个问题:很快想到是类的非静态的字段、属性。

 第二个问题:首先想到的是sizeof()。

下面开始验证,首先来验证值类型,验证代码如下:

int size = sizeof (int); //4个字节
注意点:sizeof 运算符仅适用于值类型,而不适用于引用类型。sizeof 运算符只能在不安全代码块中使用。如下面的代码将无法编译通过:

public struct TestStuct
{

}

int size = sizeof(new TestStuct());
编译后,提示:

错误 1 “ConsoleApplication3.TestStuct”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用(请考虑使用 System.Runtime.InteropServices.Marshal.SizeOf)

修改为Marshal.SizeOf方法,改方法返回对象的非托管大小(以字节为单位)。参数可以是引用类型或装箱的值类型。布局必须是连续的或显式的。

int size = Marshal.SizeOf(new TestStuct()); //1个字节
接下来

获取设备的 Device ID 可以使用 SetupApi 库的 SetupDiGetDeviceInstanceId 函数来实现。 您可以按照以下步骤进行操作: 1. 引入 SetupApi 库: ```csharp using System.Runtime.InteropServices; using System.Text; ``` 2. 定义 SetupApi 函数: ```csharp [DllImport("setupapi.dll", CharSet = CharSet.Unicode)] public static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData); [DllImport("setupapi.dll", CharSet = CharSet.Unicode)] public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, string Enumerator, IntPtr hwndParent, uint Flags); [DllImport("setupapi.dll", CharSet = CharSet.Unicode)] public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); [DllImport("setupapi.dll", CharSet = CharSet.Unicode)] public static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, int DeviceInstanceIdSize, out int RequiredSize); ``` 3. 创建获取设备 Device ID 的方法: ```csharp public static string GetDeviceID(Guid classGuid, int index) { IntPtr deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, SetupApi.DIGCF_PRESENT | SetupApi.DIGCF_PROFILE); if (deviceInfoSet.ToInt64() == -1) { return ""; } SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); deviceInfoData.cbSize = Marshal.SizeOf(deviceInfoData); if (SetupApi.SetupDiEnumDeviceInfo(deviceInfoSet, (uint)index, ref deviceInfoData)) { StringBuilder deviceInstanceId = new StringBuilder(256); int requiredSize = 0; if (SetupApi.SetupDiGetDeviceInstanceId(deviceInfoSet, ref deviceInfoData, deviceInstanceId, deviceInstanceId.Capacity, out requiredSize)) { return deviceInstanceId.ToString(); } } SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet); return ""; } ``` 4. 调用 GetDeviceID 方法: ```csharp Guid classGuid = new Guid("YOUR_DEVICE_CLASS_GUID"); int index = 0; string deviceID = GetDeviceID(classGuid, index); ``` 其,YOUR_DEVICE_CLASS_GUID 需要替换成您想要获取 Device ID 的设备的类 GUID。您可以在设备管理器找到设备的类 GUID。 另外,index 参数表示设备列表设备的索引,从 0 开始。如果需要获取所有设备的 Device ID,可以使用一个循环来遍历设备列表,并调用 GetDeviceID 方法来获取每个设备的 Device ID。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值