細說VB.NET(中)

 

細說VB.NET(中)
(作者:青蘋果工作室編譯 2001年03月07日 14:47)

易於反編譯的中間語言
  無論你用VB、C#或其它.NET語言編寫應用程序,VS.NET代碼都編譯成爲中間語言(IL)。當應用程序運行時,一個即時編譯器(JITter)處理IL代碼並把它編譯成爲機器語言。這意味着在理論上可能爲Windows以外的平臺創建.NET運行庫,但現在關於類似的事情還沒有任何官方消息。中間語言的一個缺陷是:它像VB5以前的VB版本一樣,容易被反編譯。這種可能性使許多開發者普遍地質疑.NET架構的安全性。

  CLR在IL層次內外影響代碼,對它的修改將使所有使用CLR的語言受益。然而,語言只是和代碼如何被解釋爲IL有關,對特定語言的優化可以根據特定語言的語法來編寫,這樣在技術上就可能使.NET語言之間的性能差別很小。不管怎樣,大體上藍圖是美好的。例如,CLR使VB的調試和監測工具和C#的相應工具相當,它做到了這一點因爲它們本來就是相同的工具。

  CLR提供不平行的跨語言集成,包括跨語言繼承代碼的能力。所有使用CLR的語言共享一個通用類型系統,它使使用多種語言開發應用程序變得更簡單。我不喜歡把 C API 聲明翻譯成VB裏可以使用的形式,所以我很讚賞通用類型系統帶來的好處。

  在CLR中運行的代碼被稱爲被管理代碼,被管理代碼使用的內存完全由CLR來控制。被管理代碼帶來很多好處,包括跨語言集成、跨語言異常處理和簡化的部件相互作用模型。Visual Basic被限制爲只能以被管理代碼的方式工作,然而C#擁有跳到非被管理代碼的能力(執行到運行庫之外),並能做像指針操作這類事情。這是VB和C#不同等的情況之一。這種能力到底有多重要取決於你想幹什麼。

  CLR造成的體系結構差別要比跨語言集成、共享功能和被管理代碼等深刻。首先,Visual Studio.NET的支撐結構不是 COM。另外,VB.NET裏的所有東西,甚至字符串都是對象。因爲這些和其它一些原因,Microsoft改變了支撐結構處理對象的方式。COM實現了一個引用計數方案,這樣每次引用一個對象時,計數器遞增。當一個對象引用超出作用域或被釋放時,計數器遞減,當引用計數減少到零時就終止這個對象。Microsoft聲稱在.NET架構下引用計數的開銷太大,以至於不能在 .NET中實現它,所以它放棄了引用計數轉而使用垃圾收集。

垃圾收集需要新體系結構
  CLR垃圾收集器主要是監視一個程序的資源,當可用資源達到確定的閾值時尋找無用的對象,並在發現它們的時候清除這些對象。垃圾收集的一大好處就是你不再需要擔心大多數普通的循環引用,即子對象引用了父對象,然後父對象又引用了子對象。在引用計數方案下,循環引用使兩個對象都不能被釋放和清除。然而,垃圾收集器會發現循環引用並清除它們。這也意味着釋放對象的最後一個引用時不再需要立即清除對象。

  垃圾收集的一個後果是:你再也不能指望一個類的 Terminate 事件能在適當的時機發出。實際上,如果線程被阻塞,可能根本就不會發出 Terminate 事件。和COM提供的確定化終止相反,它被稱爲不確定的終止。缺乏確定化終止,以及因爲垃圾收集器重新安排並壓縮內存從而不能使用指針的事實,在新聞組裏激發了一波激烈的辯論。我想這些新限制可能會令你痛恨,因爲你要依靠確定化終止;也可能你漠不關心,因爲你不依賴 Terminate 事件。垃圾收集並不是萬靈藥,實現弱引用依然需要做一些考慮。

  從引用計數到垃圾收集只是 Visual Studio.NET 的支撐結構不是 COM 這個事實的表象之一。你能在VB.NET中使用COM對象,比如說ActiveX服務器或ActiveX控件。然而,你必須通過包裝訪問這些對象。任何時候聽到“包裝”這個術語,你應該明白你面對着性能損失,並且對象的行爲可能有所不同。如果當計劃移植一個使用了大量COM對象的工程,就需要認真地測試和計劃,可能需要重新規劃應用程序的結構才能移植成功。坦率地說,你要有遭受挫折的準備。還記得從VBX遷移到 OCX的過程嗎?我記得,我的精神病醫生也記得。我很快就要再去看他了 ;-)

  語言本身的變化要遠遠超過體系結構的變化。大部分改變確有道理,但我並不認爲所有的改變都是如此。以前版本的VB允許你以很多方法來做很多事,以至於統一的編碼標準要麼不存在要麼就很難強加於人。Microsoft對VB做了大量的改變爲的就是“清晰”這種語言。很多情況下,原來你有好幾種方法做一件事,現在就只有一種了。Billy Hollis 提供了語法變化的詳細列表,包括廢棄的關鍵字列表,但有些東西需要在這裏重複一下。

  首先,向過程參數傳遞數據的默認方法由引用(ByRef)變成了傳值(ByVal)。這個改變主要是因爲引用要比傳值的風險大得多。它的風險主要是調用過程中的數據可能被無意中篡改。你仍然能通過引用傳遞數據,但這一改變使你需要修改新的默認調用方法來使用引用。

Set語句消失了
  其次,Set 語句消失了。在 VB.NET 裏如果你需要向變量傳遞一個對象引用,所需要的只是一個等號,對象被視爲同其它值一樣。這很酷,但也有副作用:默認屬性消失了。例如,你不再能用這種方式引用一個屬性:

  Text1 = "What, me worry?"

  作爲替代,你必須顯式地引用屬性:

  Text1.Text = "What, me worry?"

  也許一眼看來不需要這種改變,但確實必須去掉默認屬性。例如,假定你有一個叫objFoo的對象變量,不用Set語句,下面的語句所設置的引用就產生了歧義性:

  objFoo = Text1

  這條語句是應該設置到Text1的引用,還是以Text1的Text屬性來填充objFoo?你不能確定,編譯器也不能。拋棄Set語句同時要求拋棄默認屬性。

  有一個改變我不喜歡:你不再能在不同的作用域裏聲明Property Get和Property Set過程。注意 VB.NET 沒有 Property Let 語句:對象和數值都用 Property Set。這意味着你不能用一個 Friend Property Let 過程來對應一個 Public Property Get。用VB建立組件時可能會有麻煩。許多組件開發者創建 Friend Property Set 過程以使他們的應用程序能改變一個值,但提供 Public Property Get 過程以使他們的客戶程序能取回值。我希望我能爲這個改變找到一個合適的理由,可是我找不到。

  Microsoft說它力圖使語言保持清晰並使之現代化—大部分情況下它做得不錯—但這個作用域問題和其它幾個問題令人感到困惑。例如,While...Wend 很早以前就應該消失了,因爲 Do...Loop 完成同樣的功能。然而,Microsoft 不僅沒能去掉 While...Wend,還把它改成了 While...End While 來給自己找了更多的麻煩。真奇怪!

  我最不喜歡的改變是:Microsoft改變了你已經使用的數據類型含義。在 .NET 裏,Integer 現在是 32 位,而 Long 變成了 64 位。我心存恐懼地想:開發者 (包括我自己) 會多麼頻繁地使用錯誤的變量啊。那個API到底是接受一個16位的 Integer還是32位的?老天!我希望Microsoft重新考慮這個決定並使用新的變量類型,比如Int32和Long64。無論遷移到 VB.NET的移植工具是多麼的好,它也不能改變開發者的記憶。爲什麼要逼着我們再學一遍普通的數據類型呢?

  最後,最需要的一個改變是:VB.NET引入了 Option Strict 關鍵字,你可以使用它來代替 Option Explicit。Option Strict 結束了萬惡的類型強制(tm),通過它VB樂於讓你把一個數值賦值給一個字符串,然後像犯罪一樣做另一個操作。設置 Option Strict 告訴 Visual Basic.NET 不要爲你做任何類型強制。注意 VB.NET 並不是徹底的控制狂,它允許類型向下轉換,但不允許向上。例如,不使用像 sngvariable = CSng(dblvariable) 這樣的語句進行顯式類型轉換,你就不能把聲明爲 Single 的變量賦值給聲明爲 Double 的變量。因爲這有丟失數據的風險。然而,你能不使用顯式類型轉換就把聲明爲 Double 的變量賦值給聲明爲 Single 的變量,因爲這並沒有丟失數據的危險。使用 Option Strict 能幫助開發者減少很多類型錯誤,包括那些很難調錯的。但有一個附加的缺陷:在工程裏使用了 Option Strict 後,就不能進行 後編聯了。

<<<<<上一頁:概要、VB獲得了繼承能力、一切都是對象、自由線程的危險
>>>>>下一頁:表單和新IDE面孔、創建編譯的服務器端代碼、正確之路

發佈了35 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章