C#會重蹈覆轍嗎?系列之4:華而不實的C#析構器

來源:互聯網
上載者:User

前段時間去鳥國出差,顛倒黑白,碌碌無為,疏於寫博,請大家理解。下面繼續前貼7月《C與C++社區混戰,C#會重蹈覆轍嗎?》的討論。這次要談的是C#的析構器的問題。這是C#中非常華而不實的一個設計,不必要,且常常誤導很多C#er,且是.NET效能問題的常見陷阱地帶。下面逐項討論:

 

1.C#析構器是一個醜陋的文法糖

 

C#析構器(即Destructor)本質上是對Finalize方法的一個override。既然是對Finalize方法的override,那就大大方方讓程式員去override 根類Object的Finalize方法好了。可是,C#設計師們首先搞了一個析構器,接著又在編譯器裡面把父類的Finalize方法隱藏掉(你去override的時候,告訴你父類沒有Finalize方法)。但是編譯完後,在IL代碼中又告訴你override了父類中的Finalize方法,而你寫的析構器卻不翼而飛!

 

我在程式設計語言曆史上看到很多文法糖,有些文法糖華麗,有些文法糖冗贅。但是還從沒見過如此彎彎繞的文法糖!

 

2. C#析構器偏離了析構器原有的意思

 

析構器自在各程式設計語言中造始,便有以下兩大基本含義:

(a) 回收對象內部開銷的動態記憶體以及各種資源

(b) 回收具有確定性時刻,比如delete對象時,或者棧cleanup時。

 

可是C#將Finalize強扭成析構器後,徹底丟失掉前面兩大基本含義,既無法回收動態記憶體,又無法確定時刻調用(只能等GC在猴年馬月想起來才調用)。而只用於回收資源(而即便連這個任務也完成得很差,參見3.C#析構器不能完成其設計的初衷)。這使得很多沿用以前析構器概念的程式員經常犯如下錯誤,比如:

 

class MyClass { 

        object field;

     ~MyClass()   {  field=null;  }   //既不必要,也嚴重損傷效能

}

 

class MyClass { 

        object field;

     ~MyClass()   {  GC.Collect();  }   //既不必要,也嚴重、嚴重損傷效能

}

 

 

3. C#析構器不能完成其設計的初衷

 

前面說過C#析構器主要用於釋放對象的資源(非託管資源),而非記憶體。

 

但很不幸,對於C#析構器這個唯一的任務,它卻不能很好地勝任。因為C#析構器(也就是Finalize方法)是由GC調用的,而GC只會在猴年馬月想起來才調用(回收對象之前的一輪迴收),往往延誤了對象資源的釋放——而對象資源是非常昂貴的。 如果真的這樣來做的話,項目會倒大黴——比如我們以前的一個項目,有部分程式員在析構器中釋放一些native記憶體,最後導致記憶體暴漲——使用者抱怨下來,最後一調試發現原來都是在析構器惹得禍——這些析構器半天沒有被GC調用!

 

實際上,C#設計者在後來意識到這個問題了,於是又推出來一個Dispose方法(即Dispose模式)來讓使用者顯式釋放資源。然後又推薦程式員在Dispose裡面GC.SuppressFinalize(). 即屏蔽析構器。 

 

既然Dispose能將事情(確定性地釋放非託管資源)做好,析構器如此沒用,當初設計它幹嗎?這是再典型不過的多餘設計了!

 

4. C#析構器會帶來嚴重的效能障礙

 

a) C#析構器會將對象的代標記(Generation)拖大,使得對象更難以被GC回收,給GC造成更大效能負擔。

b) 析構器本身釋放資源較晚,造成資源緊張,影響系統效能。

c) 析構器執行需要一個單獨的線程開銷,該線程的執行(必須時間很短)需要其他線程停止,也是一個效能負擔。

這也是為什麼C#推薦實現Dispose,不推薦實現析構器的原因。因為析構器的效能代價太大。可能中小項目的開發人員感受不到這一點,但我相信做過大型項目的朋友,對C#析構器的效能問題會有非常深的體會。

 

綜上,C#析構器是C#設計師們純粹為了炫耀自己華麗文法糖、而不小心又失了手藝、一個拙劣的設計。

 

[ Update: ] 聽從網友的建議,把文章中“腦抽型、臭腳、sucks”等“罵街”的話刪除掉了。寫這些“罵街”的話實在是昨晚文章寫到深處,肝火旺盛,想到某些言論,情不自禁而已。並非我就是“潑婦”,今天一看自己昨晚的言論確實火力太猛,接受大家的意見,改正語言風格,希望下面堅持“技術討論不罵街“的原則。如果我有時候情不自禁做不到,希望大家監督指點,我會及時改過自新,重新做人:)  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.