.NET體系結構
主要內容包括:
C#與.NET的關系、公共語言運行庫、中間語言、程序集、.NET Framework類、名稱空間、內層管理...
C#與.NET的關系
C#是一種高級編程語言,.NET(Framework)是個環境,用C#編寫的代碼在.NET Framework中運行。
CLR公共語言運行庫
它是.NET Framework的核心,在CLR控制下運行的代碼稱為托管代碼。CLR執行編寫好的源代碼之前,需要編譯它。
編譯分兩個階段:
1)將源代碼編譯為Microsoft中間語言(IL)
2)CLR把IL編譯為平臺專用代碼。
這種設計的重要優點:
1)平臺無關性,依托的是:CTS是通用類型系統,CLS是通用語言規范,
2)提高性能
3)語言的互操作性,COM、windows運行庫
中間語言
應用程序域
就是為安全性,可靠性,隔離性,和版本控制,及卸載程序提供的隔離邊界。它通常由運行庫宿主創建,應用程序域提供了一個更安全,用途更廣的處理單元。
程序集
程序集是.NET時代的動態鏈接庫DLL,程序集是包含編譯好的、面向.NET Framework的代碼的邏輯單元。
程序集包括(中間語言(IL),元數據(metaData),資源(resource),裝配清單(AL))。
它包含的元數據(描述自身的數據)描述了對應代碼中定義的類型和方法。
可以編程訪問這些元數據,這個技術稱為“反射”。抽象工廠設計模式中有用到:
static string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name; //獲取程序集名稱 string className = AssemblyName+".Models" + "." + db + "User"; //命名空間.類名稱 (IUser)Assembly.Load(AssemblyName).CreateInstance(className); //獲取IUser程序集
可執行代碼和庫代碼,使用相同的程序集結構,他們的區別是:
可執行代碼的程序集包含一個主程序的入口點,而庫程序集不包含。
.NET Framework類
屬于托管類,使用托管代碼的好處是可以使用.NET基類庫,非常多的類的集合。大部分.net基類庫是用C#寫的。
名稱(命名)空間
是.NET避免類名沖突的一種方式。
Microsoft建議都至少要提供兩個嵌套的命名空間名,第一個是公司名,第二個是技術名稱或者軟件包的名稱,再之后是類名。
內存管理
1、GC(Garbage collector)
GC是垃圾收集器,CLR通過GC實現自動內存管理。
1)什么被認為是可回收的對象?
GC采用一定的算法遍歷所有的對象,找出可達對象和不可達對象,不可達對象是可回收的對象。
2)什么時候回收?
通常情況下:內存不足溢出時,確切的說,是第一代對象已滿的時候。
3)如何回收?
垃圾收集進程來釋放不可達對象的內存空間。
4)回收完后,還需要做什么?
避免托管堆上的內存碎片,重新分配內存,壓縮托管堆。
5)避免垃圾回收帶來的性能影響,采用代齡機制。
如要請求垃圾收集,可以調用下面的方法之一:
System.gc()
Runtime.getRuntime().gc()
2、托管資源vs非托管資源
資源就是程序中可利用的數據,譬如:字符串、圖片和任何二進制數據,包括任何類型的文件。
托管資源是由CLR全權負責的資源,CLR不負責的資源為非托管資源。
對于托管資源通過GC自動清理回收。對于非托管資源,通過代碼調用手動進行清除,再由GC回收。
如何正確的釋放資源:對于非托管的資源,一般就是,Stream(流),數據庫的連接,網絡連接等的這些操作系統資源,需要我們手動去釋放。
Net提供了三種釋放方法:Dispose,Close,析構函數(也就是Finalize方法)
3、 托管內存與非托管內存之間的轉換
c#有自己的內存回收機制,所以在c#中我們可以只new,不用關心怎樣delete,c#使用gc來清理內存,這部分內存就是managed memory,大部分時候我們工作于c#環境中,都是在使用托管內存,然而c#畢竟運行在c++之上,有的時候,(比如可能我們需要引入一些第三方的c++或native代碼的庫,在Unity3d開發中很常見)我們需要直接在c#中操縱非托管的代碼,這些non-managed memory我們就需要自己去處理他們的申請和釋放了, c# 中提供了一些接口,完成托管和非托管之間的轉換,以及對這部分內存的操作。
主要通過Marshal類和GCHandle類,編程時只要注意非托管的內存一定要負責好釋放就可以了。
例如:Marshal.AllocHGlobal()
public static IntPtr AllocHGlobal( int cb //內存中的所需字節數。 ) 通過使用指定的字節數,從進程的非托管內存中分配內存。 返回值:指向新分配的內存的指針。 必須使用釋放此內存 Marshal.FreeHGlobal 方法。 public static void FreeHGlobal( IntPtr hglobal ) IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(cardCfg)); Marshal.StructureToPtr(cardCfg, ptr, false); InrPtr是個結構體:用于表示指針或句柄的平臺特定類型。 FreeHGlobal()用法 //byte[]轉換為Intptr public static Intptr BytesToIntptr(byte[] bytes) { int size = bytes.Length; IntPtr buffer = Marshal.AllocHGlobal(size); try { Marshal.Copy(bytes, 0, buffer, size); return buffer; } finally { Marshal.FreeHGlobal(buffer); //釋放以前從進程的非托管內存中分配的內存。 } }
更多參考:
garbage-collection.md (dotnet/coreclr)

浙公網安備 33010602011771號