C#學習經驗總結
C#學習經驗之如何釋放非托管資源?
.NET 平臺在內存管理方面提供了GC(Garbage Collection),負責自動釋放托管資源和內存回收的工作,但它無法對非托管資源進行釋放,這時我們必須自己提供方法來釋放對象內分配的非托管資源,比如你在對象的實現代碼中使用了一個COM對象
最簡單的辦法,可以通過實現protected void Finalize()(析構函數會在編譯時變成這個東東)來釋放非托管資源,因為GC在釋放對象時會檢查該對象是否實現了 Finalize() 方法,如果是則調用它。但,據說這樣會降低效率……
有一種更好的,那就是通過實現一個接口顯式的提供給客戶調用端手工釋放對象的方法,而不是傻傻的等著GC來釋放我們的對象(何況效率又那么低)
System 命名空間內有一個 IDisposable 接口,拿來做這事非常合適,就省得我們自己再聲明一個接口了
另外補充一句,這種實現并不一定要使用了非托管資源后才用,如果你設計的類會在運行時有大些的實例(象 GIS 中的Geometry),為了優化程序性能,你也可以通過實現該接口讓客戶調用端在確認不需要這些對象時手工釋放它們
示例:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace Example20 {
- class Program {
- class Class1 : IDisposable {
- //析構函數,編譯后變成 protected void Finalize(),
GC會在回收對象前會調用調用該方法~Class1(){- Dispose(false);
- }
- //通過實現該接口,客戶可以顯式地釋放對象,而不需要等待GC來釋放資源,
據說那樣會降低效率void IDisposable.Dispose(){- Dispose(true);
- }
- //將釋放非托管資源設計成一個虛函數,提供在繼承類中釋放基類的資源的能力
- protected virtual void ReleaseUnmanageResources({
- //Do something……
- }
- //私有函數用以釋放非托管資源private void Dispose(bool disposing){
- ReleaseUnmanageResources();
- //為true時表示是客戶顯式調用了釋放函數,需通知GC不要再調用對象的Finalize方法
- //為false時肯定是GC調用了對象的Finalize方法,
所以沒有必要再告訴GC你不要調用我的Finalize方法啦if (disposing{- GC.SuppressFinalize(this);} static void Main(string[] args){
- //tmpObj1沒有手工釋放資源,就等著GC來慢慢的釋放它吧Class1 tmpObj1 = new Class1();
- //tmpObj2調用了Dispose方法,傳說比等著GC來釋放它效率要調一些
- //個人認為是因為要逐個對象的查看其元數據,以確認是否實現了Dispose方法吧
- //當然最重要的是我們可以自己確定釋放的時間以節省內存,優化程序運行效率
- Class1 tmpObj2 = new Class1()((IDisposable)tmpObj2)。Dispose();
- }
C#學習經驗之P/Invoke是什么?
在受控代碼與非受控代碼進行交互時會產生一個事務(transition) ,這通常發生在使用平臺調用服務(Platform Invocation Services),即P/Invoke
如調用系統的 API 或與 COM 對象打交道,通過 System.Runtime.InteropServices 命名空間,雖然使用 Interop 非常方便,但據估計每次調用事務都要執行 10 到 40 條指令,算起來開銷也不少,所以我們要盡量少調用事務,如果非用不可,建議本著一次調用執行多個動作,而不是多次調用每次只執行少量動作的原則。
C#學習經驗之StringBuilder 和 String 的區別?
String 雖然是一個引用類型,但在賦值操作時會產生一個新的對象,而 StringBuilder 則不會,所以在大量字符串拼接或頻繁對某一字符串進行操作時***使用 StringBuilder,不要使用 String
示例:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace Example22 {
- class Program {
- static void Main(string[] args){
- const int cycle = 100000;
- long vTickCount = Environment.TickCount;
- String str = null;
- for (int i = 0; i < cycle; i++)
- str += i.ToString();
- Console.WriteLine
("String: {0} MSEL", Environment.TickCount - vTickCount);- vTickCount = Environment.TickCount;
- //看到這個變量名我就生氣,奇怪為什么大家都使它呢? :)
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < cycle; i++)
- sb.Append(i);
- Console.WriteLine
("StringBuilder: {0} MSEL", Environment.TickCount - vTickCount);- Console.ReadLine();
- }
【編輯推薦】

















