DELPHI與.Net

程序開發中......... [注明:该Blog中的信息都并非原创,只是作为个人的阅读笔记]

Visual Basic 2005 中的程式語言加強功能

Visual Basic 2005 中的程式語言加強功能

作者:Stan Schultes
Microsoft MVP

2004 年 10 月

摘要:本文介紹許多 Visual Basic 2005 的全新加強功能,並提供簡單程式碼片段來說明這些功能的作用。其中涵蓋的功能包括 XML 註解、泛型 (Generics)、Global 關鍵字、部份型別、My 及其他功能。(列印共 20 頁)

注意:本文與程式碼範例是根據 Microsoft Visual Studio 2005 (之前代號為 "Whidbey") 的預先發行版寫成。在此處包含的所有資訊可能會有所變動。

目錄

簡介
My
XML 註解
泛型
Using 陳述式
Continue 陳述式
Global 關鍵字
IsNot 運算子
TryCast 陳述式
運算子多載和轉換運算子
屬性存取子存取範圍
自訂事件存取子
部份型別
應用程式層級事件
Unsigned 型別
預設執行個體
編譯器警告
明確陣列界限
結論

簡介

Visual Studio 2005 的公開 Beta 版可讓您先睹為快,所包含的各項新功能大致已底定,在 RTM 版發行前都不會有太大變更。當然其中一定會有些不同,但是最終版本與 Beta 1 版絕對是大同小異。不過仍然建議您不要在實際執行的機器上安裝 Beta 版,還是在 Microsoft Virtual PC 映像上執行比較安全。

Visual Basic 程式語言的變革重點包括 My、XML 註解及泛型。一些能夠彌補邏輯缺口的新程式語言陳述式,包括 UsingContinueTryCast,以及 Global 關鍵字。另外還有一些結構化的功能改良,包括屬性存取子存取範圍的變更、自訂事件存取子、部份型別和應用層級事件。運算子多載和轉換運算子,還有 IsNot 運算子都是新加入的。其他實用的變革包括 Unsigned 型別、表單預設執行個體、編譯器警告與明確陣列界限。

第一次啟動 Visual Studio 2005 時,程式會提示您選擇個人偏好的 IDE 設定。這些設定可以控制 IDE 索引鍵對應、視窗配置和程式碼編輯器中的程式碼格式等多項功能。您可以隨時使用 [工具 (Tools)] | [匯入/匯出設定 (Import/Export Settings)] 功能表項目 (如 [圖 1] 所示) 來變更設定值。您可以為其他程式語言匯入預設設定,也可以匯入全公司的開發人員共同使用的自訂設定。

[圖 1] 匯入自訂設定,使全公司的開發環境標準化

My

從 Visual Basic 6.0 或更早版本移轉到 .NET 時,開發人員總會面臨一項重大挑戰,也就是 .NET Framework 的龐大體積以及其命名空間階層中的類別數量。透過 .NET Framework 的基底類別庫 (Base Class Library,BCL) 可以找到常用的應用程式和環境物件,但是要熟悉它們的位置得花上一些時間。Visual Basic 2005 中新的 My 階層能提供符合邏輯的簡便方法來存取許多常用的 Framework 類別,從而加速並簡化應用程式開發作業。

My 提供兩種選擇:

  • 在 Framework 類別中提供系統化捷徑的項目。
  • 將表單、設定、資源和 Web 服務加入專案時建立的動態物件組。

My 捷徑其實就像是許多常用 BCL 物件的快速撥號設定。最上層的 My 捷徑是 My.Application、My.Computer 和 My.User,且各自包含自己的物件階層。例如,My.User 物件可以公開 AudioFileSystemKeyboardMouseNetworkRegistry 等等。

Dim sVar As String
sVar = My.User.Identity.Name
sVar = My.Computer.Info.OSFullName
sVar = My.Application.CommandLineArgs.Count.ToString

當您將表單、資源、設定和 Web 服務加入專案時,Visual Basic 會自動填入動態 My 物件。My.Resources 和 My.Settings 特別值得注意,因為當您將資源和設定加入專案時,Visual Basic 編譯器會產生強型別 (Strongly Typed) 變數參考。

在方案總管中按兩下 [我的專案 (My Project)] 項目,會帶出應用程式設計工具。按一下左邊標籤清單中的 [設定 (Settings)],如 [圖 2] 所示。

[圖 2] 顯示 [設定 (Settings)] 索引標籤的應用程式設計工具。[錯誤清單 (Error List)] 窗格顯示錯誤、警告和訊息,而且現在與 [工作清單 (Task List)] 完全分開。

加入設定名稱,例如在 User 範圍中加入數值 100 的 Integer 型別 MaxInputValue。利用完整的 IntelliSense,您可以立刻在程式碼中使用強型別物件來參考此設定,如 [圖 3] 所示。

[圖 3] 針對您在 [設定 (Settings)] 應用程式設計工具中所建立之設定值的 IntelliSense 快顯視窗範例

[設定 (Settings)] 設計工具右上角有一個標示為 [檢視程式碼 (View Code)] 的連結。按一下這個連結即可檢視名為 MySettings_user.vb 的檔案。這個檔案是部份類別,您可以在當中加入程式碼以處理設定事件,進而在設定變更時,更新應用程式的狀態 (詳細資訊請參閱〈部份型別〉一節):

Partial Public Class MySettings
    '...
End Class

此處公開三種 MySettings 事件:

  • PropertyChanged
  • SettingChanging
  • SettingsSaving

應用程式的「設定」介面屬於「可外掛式」,這表示您可以實作事件常式來定義儲存設定的方法。

您取得的強式型別與加入專案的資源相同。如果在 [資源 (Resources)] 設計工具的 [影像 (Images)] 區放入名為 Happy.bmp 的影像,您可以在程式碼中參考這個影像 (如 My.Resources.Happy)。Happy 屬於 Bitmap 型別,也就是說您無須從 Object 或 Image 型別轉換,即可在程式碼中使用這個點陣圖檔。當您在程式碼中輸入 Happy 時,IntelliSense 也會即時反應。例如:

PictureBox1.Image = My.Resources.HAPPY

這一行程式碼將此 Bitmap 物件指定為 PictureBox 的 Image 屬性。您可以看到 [圖 4] 中的 IntelliSense 快顯視窗顯示此物件屬於型別 Bitmap。

[圖 4] 將點陣圖影像拖放到應用程式設計工具的 [資源 (Resources)] 索引標籤中,便會產生可在程式碼中馬上使用的強型別物件。

將表單和 Web 服務加入專案時,My 物件會動態填入這些物件的強型別預設執行個體,供您在程式碼中參考。

誠如您所見,My 能夠方便您尋找 BCL 類別的相關應用程式與環境,並以強型別的方式讓您立即存取範圍、資源以及加入專案的其他物件。上述優點將大幅提昇各級 Visual Basic 開發人員的生產力。

XML 註解

XML 註解可讓您在程式碼中加入結構化文件,開始是 C# 先採用,為此還讓 Visual Basic 的開發人員欣羨不已。XML 註解可以描述各種程式碼項目,包括類別、欄位、方法和列舉。

一旦建立描述程式碼功能的 XML 註解之後,當您在編輯器中鍵入程式碼功能時,IntelliSense 便會立即顯示參數和傳回型別。假設您有一個函式原型包含下列簽章:

Private Function GetCustomerData(ByVal CustomerCode As String) _
    As DataSet

將程式碼插入點放在函式宣告的上一行,並鍵入三個單引號字元。Visual Basic 會產生符合此函式宣告的 XML 註解範本,讓您像在表單般使用 Tab 鍵進行填寫。假設您為函式的註解範本填入以下內容:

''' <summary>
''' Returns a DataSet for a single customer.
''' </summary>
''' <param name="CustomerCode">Customer Code as String.</param>
''' <returns>DataSet for the supplied CustomerCode.</returns>
''' <remarks>Resides in the application's data layer.</remarks>

當您在程式碼的其他地方鍵入這個函式名稱時,便會顯示包含函式摘要、參數和傳回值的完整 IntelliSense,如 [圖 5] 所示。

[圖 5] 此工具提示顯示當您將 XML 註解加入程式碼項目時,取得的 IntelliSense 即時回應。

對於企業和團隊環境而言,這是一項關鍵功能。您可以利用來源檔案中插入的結構化 XML 註解來產生程式碼文件。此外,應用程式設計師或首席開發人員可以在實作前先建立功能原型並加上註解。當開發人員使用原型物件來撰寫程式碼時,IntelliSense 會指導他們如何正確使用功能。

編譯器會將 XML 註解視為程式碼不可或缺的部份。註解標記值像註解一樣是彩色的,如果對 XML 註解進行大綱摺疊,那麼只會顯示代表整個 XML 註解範本的摘要標記值 (請見 [圖 6])。

[圖 6] XML 註解與編譯器及程式碼視窗完全整合。FillDataGrid 函式的 XML 註解摺疊成摘要行。

如果將函式原型的 CustomerCode 參數名稱變更為 CustomerID,編譯器就會在 <param name="CustomerCode"> 標籤底下加上綠色曲線,用意在警告這兩個名稱不符 (詳細資訊請參閱〈編譯器警告〉一節)。

在您建立專案時,Visual Basic 會自動產生 XML 文件檔案。這個檔案會以 AssemblyName.xml 的名稱出現在應用程式輸出目錄中。由於這是 XML 檔案,因此可輕易將之轉換成其他必要的輸出格式。XML 註解使您為程式碼產生文件更加得心應手,不但可以在編寫程式碼時當作 IntelliSense,還可以在建置應用程式後當作程式碼文件來使用。

泛型

BCL 現在提供 System.Collections.Generic 命名空間,其中包含多種類別定義泛型集合。之所以稱為泛型是因為在宣告時,您是為內含的物件指定型別替代符號,而非特定型別。只有在建立集合的執行個體時,才會為儲存物件提供特定型別。

泛型可省下大量的時間。要是您曾經建立過自訂集合,您就知道要撰寫的程式碼有多少。有了 Visual Basic 的泛型功能,您只要使用一行程式碼即可建立自訂集合的相同對應項。再也不用針對要儲存的每個物件型別,逐一建立自訂集合。只需要在產生泛型集合時,提供想要的型別即可。

要瞭解泛型的運作方式,最簡單的辦法就是舉例來說明。假設有一個包含兩種公用屬性 (為求簡便,以公用變數表示) 的簡單 Customer 類別:

Public Class Customer
    Public Name As String
    Public CreditLimit As Decimal

    Public Sub New(ByVal CustomerName As String, _
      ByVal CustCreditLimit As Decimal)
        Name = CustomerName
        CreditLimit = CustCreditLimit
    End Sub
End Class

您可以使用泛型集合 List 類別來宣告 Customers 清單,如下所示:

Dim Customers As New System.Collections.Generic.List(Of Customer)

利用這樣一行程式碼,您就宣告了專門儲存 Customer 型別的強型別清單,並且獲得包含 Customer 物件的完整 IntelliSense。您只要輕鬆地建立一份 ProductOrder 物件的清單,即可有效建立一組自訂集合,而無須針對每個型別撰寫所有的自訂集合程式碼。您現在可以將程式碼寫成這樣:

Dim custA As New Customer("CustA", 1000)
Customers.Add(custA)
Dim custB As New Customer("CustB", 2000)
Customers.Add(custB)
For Each c As Customer In Customers
    MessageBox.Show("Customer: " & c.Name & _
      ", limit: " & c.CreditLimit)
Next

'compile error: Product cannot be converted to Customer
Dim prodA As New Product("ProdA", CDec(29.95))
Customers.Add(prodA) 

使用泛型集合還可達到效能優勢,因為儲存物件屬於強型別,而不是保留在內部的 Object 型別。

System.Collections.Generic 命名空間還提供其他集合泛型。例如,Dictionary(of K,V) 集合可讓您指定索引鍵和數值的型別。LinkedList(of T) 與 Stack(of T) 泛型集合的行為模式就像一般的連結清單和堆疊,只差您可以指定其中包含的物件類型。

您可以使用新的泛用型別宣告語法來建立自己的泛用型別。就 Comparer 類別而言,此類別可讓您比較不同的物件類型:

Public Class Comparer(Of itemType)
    '...
End Class

您可以在以逗點分隔的清單中定義多種型別替代符號;也可以定義條件約束,以便限定當泛型產生時,要提供哪些類別給它:

Public Class Comparer(Of itemType As IComparable)
    '...
End Class

此條件約束可確保 Comparer(of T) 執行個體只有在類別實作 IComparable 介面時,才能建立。類別宣告也可以同時套用數個條件約束。

現以實作 IComparable 的擴充 Customers 類別為例:

Public Class Customer
    Implements IComparable
    Public Name As String
    Public CreditLimit As Decimal

    Public Sub New(ByVal CustomerName As String, _
      ByVal CustCreditLimit As Decimal)
        Name = CustomerName
        CreditLimit = CustCreditLimit
    End Sub

    Public Function CompareTo(ByVal obj As Object) As Integer _
      Implements IComparable.CompareTo
        Dim c As Customer = CType(obj, Customer)
        If CreditLimit > c.CreditLimit Then Return 1
        If CreditLimit < c.CreditLimit Then Return -1
        Return 0
    End Function
End Class

以下實作類似的 Product 類別,只不過 CompareTo 函式是比較產品價格而非客戶的信用額度:

Public Class Product
    Implements IComparable
    Public Name As String
    Public Price As Decimal

    Public Sub New(...)...
    Public Function CompareTo(...)...
End Class

現在 Comparer 類別提供泛型比較運算:

Public Class Comparer(Of itemType As IComparable)
    Public Function GetLargest(ByVal Item1 As itemType, _
    ByVal Item2 As itemType) As itemType
        Dim i As Integer = Item1.CompareTo(Item2)
        If i > 0 Then Return Item1
        If i < 0 Then Return Item2
        Return Nothing
    End Function
End Class

您現在可以產生各種物件類型的 Comparers

Dim pc As New Comparer(Of Product)
Dim prod1 As New Product("LittleOne", 10)
Dim prod2 As New Product("BigOne", 100)
Dim lp As Product = pc.GetLargest(prod1, prod2)
MessageBox.Show("The more expensive product is: " & lp.Name)

Dim cc As New Comparer(Of Customer)
Dim cust1 As New Customer("SmallCo", 1000)
Dim cust2 As New Customer("LargeCo", 5000)
Dim lc As Customer = cc.GetLargest(cust1, cust2)
MessageBox.Show("The customer with a higher limit is: " & lc.Name)

如果沒有泛型,您就得要針對每個需要比較的物件類型,逐一定義比較類別 (例如,ProductComparerOrderComparer)。

在許多常見的案例中,泛型將幫助您大幅減輕編碼的工作。如果您要處理多種類別,而其中的差異僅止於所操作的物件類型,那麼您可以考慮使用泛型。

Using 陳述式

Using 陳述式是一種便捷的方法,可讓您取得物件、對物件執行程式碼、以及立刻釋放物件。有些架構物件,例如圖形、檔案控制代碼、通訊連接埠和 SQL 連接,會要求您釋放所建立的物件,以免應用程式發生記憶體遺漏的情況。假設您想用 Brush 物件來繪製矩形:

Using g As Graphics = Me.CreateGraphics()
    Using br As System.Drawing.SolidBrush = _
        New SolidBrush(System.Drawing.Color.Blue)
        g.FillRectangle(br, New Rectangle(30, 50, 230, 200))
    End Using
End Using

若您要立即處置用完的 Graphics 及 Brush 物件,Using 陳述式可讓您在彈指之間就完成這項作業。相較於 Visual Basic .NET 的作法 (使用 Try / Catch 並在 Finally 區塊中釋放物件),Using 陳述式更加簡潔。

Continue 陳述式

Continue 陳述式會跳到下一個迴圈反覆運算,讓迴圈邏輯更精準、更易於讀取:

Dim j As Integer
Dim prod As Integer
For i As Integer = 0 To 100
    j = 0
    While j < i
        prod = i * j
        If prod > 5000 Then
            'skips to the next For value
            Continue For
        End If
        j += 1
    End While
Next

Continue 陳述式非常乾淨俐落,無須借助標籤和 goto 陳述式,就能輕鬆跳脫內部迴圈。Continue 陳述式只在 For、While 和 Do 迴圈上運作。

Global 關鍵字

Global 關鍵字可讓您存取命名空間階層最上方的根命名空間 (或稱空白命名空間)。在過去,您並無法定義公司命名空間階層中的 System.IO 命名空間:

Namespace MyCompany.System.IO

因為這麼做會弄亂應用程式中所有對於架構的 System 命名空間的參考。不過您現在可以使用 Global 關鍵字來釐清命名空間:

Dim myFile As Global.System.IO.File

在產生程式碼時,若要確保所產生的命名空間參考一定指向您要的目標,這時 Global 關鍵字就特別好用。我相信您會看到 Visual Basic 在所有產生的程式碼中也都使用 Global 關鍵字。

IsNot 運算子

IsNot 運算子擔任 Is 運算子的對等角色。IsNot 可讓您使用直接比較並排除 Not 運算子:

If myObj IsNot Nothing Then

同理,若要檢查兩個物件執行個體的異同,您也可以排除 Not 運算子:

If MyObj1 IsNot MyObj2 Then

雖然這只是小改變,但是 IsNot 可以填補 Visual Basic 程式語言的不一致漏洞,讓程式碼更為精簡。

TryCast 陳述式

Visual Basic 2003 提供兩種方法讓您將物件型別轉換成另一種型別:

Dim p As Product 
p = CType(obj, Product)
p = DirectCast(obj, Product)

此處您使用 CType 來轉換型別,但 DirectCast 要求這些物件之間必須存在繼承或實作關係。問題出在如果 obj 無法轉換成型別 Product 時,兩者都會顯示 Run-Time 例外狀況。

輸入新的 TryCast 陳述式。使用方法與 CTypeDirectCast 一樣,但是如果轉換不成功,傳回的結果將是 Nothing

p = TryCast(obj, Product)
If p IsNot Nothing Then
    'use the p object...
End If

運算子多載和轉換運算子

Visual Basic 2005 其中一項最有力的新增功能就是運算子多載。運算子多載可讓您定義在任何所需型別上執行的運算子,甚至可讓您建立自己的基底型別。

複數加總是一個典型的運算子多載範例。包含 + 運算子多載的簡單 Complex 類別可能如下所示:

Public Class Complex
    Public Real As Double
    Public Imag As Double

    Public Sub New(ByVal realPart As Double, ByVal imagPart As Double)
        Real = realPart
        Imag = imagPart
    End Sub

    Shared Operator +(ByVal lhs As Complex, ByVal rhs As Complex) _
        As Complex
        Return New Complex(lhs.Real + rhs.Real, lhs.Imag + rhs.Imag)
    End Operator
End Class

使用 + 運算子來進行直覺式的複數加總:

Dim lhs As Complex = New Complex(2.0, 2.5)
Dim rhs As Complex = New Complex(3.0, 3.5)
Dim res As Complex = lhs + rhs
'res.real = 5.0, res.imag = 6.0

您也可以多載自訂型別的轉換運算子。若要將 res 值轉換為 CType(res,String),將會出現編譯器錯誤:Complex 不能轉換成 String。在預設情況下,若要查看 Res.ToString 的值,將會傳回 Complex 值,且 ToString 會顯示型別名稱。利用多載 CType 轉換運算子和 ToString 方法,即可解決這些問題,如下所示:

Public Shared Narrowing Operator CType(ByVal Value As Complex) _
    As String
    Return Value.Real.ToString & "i" & Value.Imag.ToString
End Operator

Public Overrides Function ToString(ByVal Value As Complex) As String
    Return Value.Real.ToString & "i" & Value.Imag.ToString
End Function

如此一來,傳回的 CType(res,String) 和 res.ToString 值就符合您所預期的:"5.0i6.0"。轉換運算子必須宣告為縮小 (Narrowing) 或擴展 (Widening),藉此表示轉換的執行方式。

屬性存取子存取範圍

Visual Basic .NET 屬性有個令我困擾已久的問題,那就是 GetSet 存取子必須使用相同的存取範圍 (Public、Friend 或 Private)。如果您想建立唯讀的公用屬性 (只有 Get 是公用),那麼元件中就沒有可以用來執行驗證或自訂屬性處理的 Set 存取子。

現在,Visual Basic 2005 中的 GetSet 存取子可以使用不同的存取範圍,只要 Set 的限制比 Get 嚴格即可:

Private _myProp As String
Public Property MyProp() As String
    Get
        Return _myProp
    End Get
    Friend Set(ByVal value As String)
        If value.Trim.Length > 0 Then
            _myProp = value.Trim
        Else
            value = "<no value>"
        End If
    End Set
End Property

對於在團隊開發環境中,以及力求徹底重複利用程式碼的個別開發人員而言,這是非常實用的功能。

自訂事件存取子

事件存取子可讓您定義自訂事件,還可以控制當用戶端加入或移除處理常式,並引發您的事件時該如何處理。假設您引發自訂類別的事件 RateChanged。宣告一般事件的方法有兩種,您可以擇一使用:

Public Event RateChanged()
  'or
Public Event HoursChanged As EventHandler

使用這種方法宣告的事件會自動管理備份。換句話說,系統可決定如何管理和分派事件。通常這不會有問題,但有時您需要特別控制事件接聽項的通知方式。

您使用新的 Custom 關鍵字來宣告自訂事件與其存取子。只要您一按下事件宣告的 Enter 鍵,Visual Basic 2005 便會為您建立程式碼原型,其方式與產生 Property 存取子的方法一樣:

Public Custom Event NameChanged As EventHandler
    AddHandler(ByVal value As EventHandler)
        'hook handler to backing store
    End AddHandler

    RemoveHandler(ByVal value As EventHandler)
        'remove handler from backing store
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
        'invoke listeners
    End RaiseEvent
End Event

當用戶端在您的事件加入或移除處理常式時,便會執行 AddHandlerRemoveHandler 常式。當事件被引發時,便會執行 RaiseEvent 常式。如此一來,您可以根據您對管理事件備份的需求來採取特別行動。當您以這種方法建立自訂事件時,可把它當作是屬性。

這在您的物件已經序列化,但您的事件卻是由非序列化的委派物件來處理的情況下蠻實用的。如果使用一般事件來序列化物件,序列化作業將會失敗,因為事件備份無法序列化。Rocky Lhotka (另一位 Visual Basic MVP) 詳細解說了這種情況,並在 Blog 中提供了詳細的範例:http://www.lhotka.net/WeBlog/CommentView.aspx?guid=776f44e8-aaec-4845-b649-e0d840e6de2c (英文)。

部份型別

部份型別可用來定義橫跨多重原始程式檔的單一型別。型別定義在單一檔案中有一般宣告:

Public Class TestPartial
    'implementation...
End Class

在其他原始程式檔中,您使用 Partial 關鍵字來告知編譯器,這段程式碼是接續原始的類別定義:

Partial Public Class TestPartial
    'implementation...
End Class

由 IDE 中的設計工具所產生的類別程式碼會標示為 Partial 關鍵字,並與使用者程式碼相互區隔。將名為 TestForm 的表單加入專案中,並觀察產生的原始程式檔。您可能會很驚訝地發現除了表單的類別宣告以外,其他一無所有。所有由設計工具產生、以便進入 Windows 表單設計工具產生的程式碼區域的程式碼都到哪去了?

設計工具產生的程式碼現在位於 TestForm.designer.vb 檔案中,只要在方案總管工具列上按一下 [顯示所有檔案 (Show All Files)] 按鈕就能看到這個檔案。您不應該變更此檔案中的程式碼,但是之後如果想在設計工具檔案再產生之前保留某些程式碼的話,可將所需內容複製並貼至 TestForm.vb 檔案中。

專案團隊可以將一個包含部份其所屬類別的檔案指派給各個開發人員,藉此發揮部份類別的功用。 多位開發人員不必再與別人存取相同的原始程式檔,因為您現在可以將類別定義區分成多個原始程式檔。

應用程式層級事件

另一個您會喜歡使用的新功能是應用程式層級事件組,由名為 MyApplication 的部份類別所提供。在方案總管的 [我的專案 (My Project)] 項目中尋找名為 MyEvents.vb 的檔案。在應用程式設計工具的 [應用程式 (Application)] 索引標籤中,按一下 [檢視程式碼 (View Code)] 按鈕也可以找到這個檔案。

這些新的應用程式層級事件很像是 ASP.NET 應用程式中 global.asax 檔案的應用程式事件。當中會公開五個事件:

  • Shutdown
  • Startup
  • StartupNextInstance
  • NetworkAvailabiltyChanged
  • UnhandledException

啟動和關閉應用程式時會引發前三個事件。機器上的網路狀態發生變更時會引發 NetworkAvailabilityChanged。請在 UnhandledException 事件中加入程式碼,以免擲回無法在別處處理的例外狀況。

Unsigned 型別

Visual Basic 2005 完全支援 Unsigned 型別。Unsigned 型別名稱如下:

  • SByte
  • UShort
  • UInteger
  • ULong

Unsigned 型別的運作方式與一般型別一樣,但是 Unsigned 型別只能儲存正整數。

Unsigned 型別特別適合在 Visual Basic 中用於進行 Win32 API 呼叫,此呼叫會將 Unsigned 型別視為參數。下列程式碼解說 Windows MessageBox API 呼叫:

Public Enum WindowsMessageResult As UInteger
    OK = 1
    Cancel = 8
End Enum

Private Const MB_OK As UInteger = 0
Private Const MB_ICONEXCLAMATION As UInteger = &H30
Private Const MB_OPTIONS As UInteger = MB_OK Or MB_ICONEXCLAMATION

Private Declare Auto Function Win_MB Lib _
    "user32.dll" Alias "MessageBox" _
    (ByVal hWnd As Integer, ByVal lpText As String, _
    ByVal lpCaption As String, ByVal uType As UInteger) _
    As UInteger

Public Function MessageThroughWindows(ByVal message As String, _
    ByVal caption As String) As WindowsMessageResult
    Dim r As UInteger = Win_MB(0, message, caption, MB_OPTIONS)
    Return CType(r, WindowsMessageResult)
End Function

請注意,Win_MB 宣告的最後一個參數和傳回型別都是 UInteger 型別。

如需儲存大於 Integer 的數值,Unsigned 型別也可以幫您節省記憶體。Integer 型別會佔用四個位元組的記憶體,而且最多可以儲存 2,147,483,648 的正數及負數值。UInteger 型別也會佔用四個位元組,並且可以儲存介於零到 4,294,967,295 之間的數值。如果沒有 Unsigned 型別,您就必須使用 Long 來儲存這麼龐大的數值,而 Long 會佔用八個位元組的記憶體。

預設執行個體

Visual Basic .NET 的另一項變更是預設執行個體,過去使得許多開發人員一直不想從 Visual Basic 6.0 遷移的主因正是因為表單沒有預設執行個體。您必須先建立表單的執行個體,才能開始使用:

Dim frm As New Form2
frm.Show()

Visual Basic 2005 支援表單預設執行個體,所以您可以使用熟悉的語法:

Form2.Show()

如果從 My.Forms 集合存取此預設表單執行個體,那就再好不過了:

My.Forms.Form2.Show()

編譯器警告

Visual Basic 2005 支援編譯器警告,讓您提防 Run Time 時可能發生的問題。程式碼底下的綠色曲線就表示警告 (錯誤則以藍色曲線表示)。

編譯器警告包括遞迴屬性存取、重疊 Catch 區塊或 Case 陳述式、建立沒有傳回值的函式等等。我的最愛警告適用於未初始化物件的變數參考:

Dim cust As Customer
If cust.Name.Length = 0 Then
  '...
End If

如上所示,背景編譯器在 If 陳述式的 cust 底下加上綠色曲線。顯示的警告文字為:「變數 'cust' 尚未指派值即使用」。Run Time 可能會產生 Null 參考例外狀況。我的程式碼在 Run Time 時發生這種錯誤的次數已經多到數不清,現在編譯器終於可以在編譯階段找出這些錯誤了。

附帶一提,當您在編譯器中鍵入以上程式碼時,編譯器一開始會在 Dim 陳述式的 cust 底下加上綠色曲線,並顯示「未使用的區域變數 'cust'」的訊息。剛開始您可能會覺得很煩,因為您已經加入變數了,但是這項功能最終還是有助於保持程式碼簡潔。

這裡不會在 IDE 中將所有錯誤顯示在 [工作清單 (Task List)] 中,而是使用新的 [錯誤清單 (Error List)] 視窗,分別顯示錯誤、警告、和訊息 (請見 [圖 2] 及 [圖 6])。您在應用程式設計工具的 [編譯 (Compile)] 索引標籤上,多少能夠控制編譯器是要標記警告或錯誤,其中的核取方塊可用來停用所有警告,或者將所有警告視為錯誤。

在不同的情況下可使用 Option Strict On 陳述式來產生編譯時期錯誤。如果您嘗試進行隱含縮小轉換 (可能會造成資料遺失),Option Strict 便會標記您的程式碼:

Dim iValue As Integer
Dim lValue As Long
iValue = lValue     'narrowing conversion error
lValue = iValue     'ok

使用晚期繫結也會產生錯誤。將物件指派給型別 Object 的變數,便會造成物件晚期繫結:

Dim myObj As Object
Call myObj.method1()    'late binding error

使用 Option Strict 可說是 Visual Studio 的最佳程式設計實例。您應該在程式碼中盡可能啟用 Option Strict。只要在 [工具 (Tools)] | [選項 (Options)] 功能表中,選取 [專案 (Project)] 設定下的 [Option Strict] 核取方塊,即可啟用 Option Strict。您也可以將 Option Strict On 陳述式加入個別類別或模組檔案的最上方。

明確陣列界限

您現在可以使用明確陣列界限來宣告陣列,好讓宣告更清楚:

Dim a(10) As Integer        'old way
Dim b(0 To 10) As Integer   'new way

Visual Basic 中的陣列界限依舊以零為基底,因此如果陣列界限下限值不是 0,便會產生編譯器錯誤。

結論

Visual Basic 2005 程式語言結合了好幾個主要功能和許多次要的增強功能,一起大幅提昇使用便利性和開發人員的生產力。程式語言不但變得更加完整,而且在 XML 註解及運算子多載等重大功能方面,足以與 C# 相互匹敵。

與各種 IDE 增強功能相加整合之後,Visual Basic 2005 勢必成為有史以來最佳的 Visual Basic 版本。不僅程式語言功能令人滿意,使用起來更是得心應手。唯一讓我失望的是,目前還不能使用 Visual Basic 2005 來建置生產應用程式。只要用過 Beta 版,相信您也會深表同感。

posted on 2005-10-17 20:29  人淡如菊  阅读(1044)  评论(0编辑  收藏  举报

导航