C# 能否获取一个对象所占内存的大小?
今日,在項(xiàng)目重構(gòu)的時(shí)候忽然想到一個(gè)問題,一個(gè)類哪些成員的增加,會(huì)影響一個(gè)類所占內(nèi)存的大小?C#有沒有辦法知道一個(gè)對(duì)象占多少內(nèi)存呢?
? ? ?第一個(gè)問題:很快想到是類的非靜態(tài)的字段、屬性。
? ? ?第二個(gè)問題:首先想到的是sizeof()。
下面開始驗(yàn)證,首先來驗(yàn)證值類型,驗(yàn)證代碼如下:
int size = sizeof (int); //4個(gè)字節(jié)注意點(diǎn):sizeof?運(yùn)算符僅適用于值類型,而不適用于引用類型。sizeof?運(yùn)算符只能在不安全代碼塊中使用。如下面的代碼將無法編譯通過:
public struct TestStuct{}int size = sizeof(new TestStuct());編譯后,提示:
錯(cuò)誤 1 “ConsoleApplication3.TestStuct”沒有預(yù)定義的大小,因此 sizeof 只能在不安全的上下文中使用(請(qǐng)考慮使用 System.Runtime.InteropServices.Marshal.SizeOf)?
修改為Marshal.SizeOf方法,改方法返回對(duì)象的非托管大小(以字節(jié)為單位)。參數(shù)可以是引用類型或裝箱的值類型。布局必須是連續(xù)的或顯式的。
int size = Marshal.SizeOf(new TestStuct()); //1個(gè)字節(jié)接下來來驗(yàn)證引用類型:
由于不能作為非托管結(jié)構(gòu)進(jìn)行封送處理;無法計(jì)算有意義的大小或偏移量。所有下面的代碼在運(yùn)行的時(shí)候,會(huì)拋出異常。
public class Student{}int size = Marshal.SizeOf(new Student());需要給Student類,加上一個(gè)StructLayoutAttribute,來控制Student類的數(shù)據(jù)字段的物理布局。修改代碼為:
[StructLayout(LayoutKind.Sequential)]public class Student{}int size = Marshal.SizeOf(new Student()); //1個(gè)字節(jié)LayoutKind 默認(rèn)值為Auto.
結(jié)論:
1:對(duì)于托管對(duì)象是沒有辦法直接獲取到一個(gè)對(duì)象所占的內(nèi)存大小。
2:非托管對(duì)象,可以使用Marshal.SizeOf
3:對(duì)內(nèi)置類型,如int,long,byte等使用sizeof
擴(kuò)展:
有人提出使用二進(jìn)制序列化,將一個(gè)對(duì)象序列化成一個(gè)MemoryStream,然后返回MemoryStream.Length,經(jīng)過驗(yàn)證是不可以的。
驗(yàn)證代碼如下:
Student.txt保存的文本信息如下所示,通過文本信息,可以得知多出來的100多個(gè)字節(jié),估計(jì)是就是這一串字符串吧。
JConsoleApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ConsoleApplication3.Student?
延伸閱讀:
http://blogs.msdn.com/b/cbrumme/archive/2003/04/15/51326.aspx
原文如下:
We don't expose the managed size of objects because we want to reserve the ability to change the way we lay these things out.??For example, on some systems we might align and pack differently.??For this to happen, you need to specify tdAutoLayout for the layout mask of your ValueType or Class.??If you specify tdExplicitLayout or tdSequentialLayout, the CLR’s freedom to optimize your layout is constrained.
If you are curious to know how big an object happens to be, there are a variety of ways to discover this.?You can look in the debugger.??For example, Strike or SOS (son-of-strike) shows you how objects are laid out.??Or you could allocate two objects and then use unverifiable operations to subtract the addresses.?99.9% of the time, the two objects will be adjacent.??You can also use a managed?profiler?to get a sense of how much memory is consumed by instances of a particular type.
But we don't want to provide an API, because then you could form a dependency over this implementation detail.
Some people have confused the System.Runtime.InteropServices.Marshal.SizeOf() service with this API.?However, Marshal.SizeOf reveals the size of an object after it has been marshaled.??In other words, it yields the size of the object when converted to an unmanaged representation.??These sizes will certainly differ if the CLR’s loader has re-ordered small fields so they can be packed together on a tdAutoLayout type.
? #1樓?2013-05-16 16:23?jintianzhang? 可以考慮GC.GetTotalMemory方法 支持(0)反對(duì)(0) #2樓[樓主]?2013-05-16 16:55?supperwu? @jintianzhang如何用?請(qǐng)指教。 支持(0)反對(duì)(0) #3樓[樓主]?2013-05-16 16:59?supperwu? @jintianzhang
var student = new Student();
long size = GC.GetTotalMemory(true); //95028個(gè)字節(jié)
Student沒有任何成員。 支持(0)反對(duì)(0) #4樓[樓主]?2013-05-16 17:11?supperwu? @jintianzhang
GC.Collect(0);
var student = new Student();
long n = GC.GetTotalMemory(true);
student = null;
GC.Collect(0);?
long m = GC.GetTotalMemory(true);
Console.WriteLine(n - m); //12個(gè)字節(jié) 支持(0)反對(duì)(0) #5樓?2013-05-16 20:50?AlexanderYao? [StructLayout(LayoutKind.Sequential)]
呵呵,學(xué)習(xí)了! 支持(0)反對(duì)(0) #6樓[樓主]?2013-05-16 22:44?supperwu? @AlexanderYao
謝謝支持!多多賜教! 支持(0)反對(duì)(0) #7樓?2013-05-16 23:58?jintianzhang? @supperwu
GC.Collect();
GC.WaitForFullGCComplete();
long start = GC.GetTotalMemory(true);
Student student = new Student();
GC.Collect();
GC.WaitForFullGCComplete();
long end = GC.GetTotalMemory(true);
Console.WriteLine(end-start);//12
這是比較接近的值 支持(0)反對(duì)(0) #8樓?2013-06-16 21:23?永遠(yuǎn)的阿哲? 學(xué)習(xí)了! 支持(0)反對(duì)(0) #9樓?2013-09-09 09:51?zwq_sj? 整個(gè)系統(tǒng)是單線程環(huán)境下時(shí)才能使用GC.GetTotalMemory 支持(0)反對(duì)(0) #10樓?2014-01-09 10:11?halon? enum呢?
出處:http://www.cnblogs.com/supperwu/archive/2013/05/16/3082061.html
轉(zhuǎn)載于:https://www.cnblogs.com/mq0036/p/3595436.html
總結(jié)
以上是生活随笔為你收集整理的C# 能否获取一个对象所占内存的大小?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 描写疼痛难忍的句子 表达疼痛难忍的句子怎
- 下一篇: 妙用iPhone全景拍摄:拍出分身