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個字節接下來來驗證引用類型:
由于不能作為非托管結構進行封送處理;無法計算有意義的大小或偏移量。所有下面的代碼在運行的時候,會拋出異常。
public class Student{}int size = Marshal.SizeOf(new Student());需要給Student類,加上一個StructLayoutAttribute,來控制Student類的數據字段的物理布局。修改代碼為:
[StructLayout(LayoutKind.Sequential)]public class Student{}int size = Marshal.SizeOf(new Student()); //1個字節LayoutKind 默認值為Auto.
結論:
1:對于托管對象是沒有辦法直接獲取到一個對象所占的內存大小。
2:非托管對象,可以使用Marshal.SizeOf
3:對內置類型,如int,long,byte等使用sizeof
擴展:
有人提出使用二進制序列化,將一個對象序列化成一個MemoryStream,然后返回MemoryStream.Length,經過驗證是不可以的。
驗證代碼如下:
Student.txt保存的文本信息如下所示,通過文本信息,可以得知多出來的100多個字節,估計是就是這一串字符串吧。
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)反對(0) #2樓[樓主]?2013-05-16 16:55?supperwu? @jintianzhang如何用?請指教。 支持(0)反對(0) #3樓[樓主]?2013-05-16 16:59?supperwu? @jintianzhang
var student = new Student();
long size = GC.GetTotalMemory(true); //95028個字節
Student沒有任何成員。 支持(0)反對(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個字節 支持(0)反對(0) #5樓?2013-05-16 20:50?AlexanderYao? [StructLayout(LayoutKind.Sequential)]
呵呵,學習了! 支持(0)反對(0) #6樓[樓主]?2013-05-16 22:44?supperwu? @AlexanderYao
謝謝支持!多多賜教! 支持(0)反對(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)反對(0) #8樓?2013-06-16 21:23?永遠的阿哲? 學習了! 支持(0)反對(0) #9樓?2013-09-09 09:51?zwq_sj? 整個系統是單線程環境下時才能使用GC.GetTotalMemory 支持(0)反對(0) #10樓?2014-01-09 10:11?halon? enum呢?
出處:http://www.cnblogs.com/supperwu/archive/2013/05/16/3082061.html
轉載于:https://www.cnblogs.com/mq0036/p/3595436.html
總結
以上是生活随笔為你收集整理的C# 能否获取一个对象所占内存的大小?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 描写疼痛难忍的句子 表达疼痛难忍的句子怎
- 下一篇: 妙用iPhone全景拍摄:拍出分身