Visual Basic 編碼慣例

Microsoft 使用這些方針來開發範例和文件, Visual Basic 語言規格並未定義編碼標準。

  • 編碼慣例會建立一致的程式碼外觀,以便讀取器 (Reader) 可以將焦點放在內容,而非配置。

  • 慣例可讓讀取器更迅速地了解程式碼,因為這可供讀取器根據先前的經驗進行假設。

  • 慣例使得複製、變更和維護程式碼變得更加容易。

  • 慣例會示範 Visual Basic 的「最佳作法」。

討論

命名規範

  • 開發類別庫的設計方針中涵蓋了命名方針。

  • 您不必變更 Visual Studio 設計工具所建立的物件名稱,就可以讓它們符合方針。

  • 使用命名空間 (Namespace) 限定性條件,而非加入 Imports 陳述式。 如果依預設在專案中匯入了命名空間,您不必完整限定程式碼,因為在複製和貼上時,它將利用 IntelliSense 以未限定方式執行。 當您分割長的程式碼行使其更容易閱讀時,可在 "." 之後分割限定名稱 (Qualified Name)。例如:

    Dim collection As System.Diagnostics. 
           InstanceDataCollectionCollection
    
  • 請不要使用 "My" 或 "my" 做為變數名稱的一部分。 這會與 My 物件產生混淆。

配置慣例

好的配置會使用格式化來強調程式碼的結構,並使程式碼更容易閱讀。

  • 使用美化排列功能的預設設定 (智慧型縮排、4 個字元縮排、將定位點儲存為空格),將程式碼格式化。 如需詳細資訊,請參閱選項對話方塊、文字編輯器、Basic、VB 專用

  • 每行只使用一個陳述式。 請不要使用 Visual Basic 行接續字元 (:)。

  • 每行只使用一個宣告。

  • 如果美化排列沒有格式化連續行,則將連續行縮排一個定位停駐點 (Tab Stop)。

  • 在方法與屬性定義之間加入至少一個空白行。

註解慣例

  • 請不要在程式碼行的結尾使用註解, 將註解放在個別一行。

  • 以大寫字母做為註解文字開頭。

  • 以句號結束註解。

  • 在註解分隔符號 (') 與註解文字之間插入一個空格。

    ' Here is a comment.
    
  • 請不要建立在註解周圍,並且已格式化的星號區塊。

程式結構

  • 在使用 Main 方法時,請對新的主控台應用程式 (Console Application) 使用預設建構,並對命令列引數使用 My。

    Sub Main()
      For Each argument As String In My.Application.CommandLineArgs
        ' Add code here to use the string variable.
      Next
    End Sub
    

語言方針

字串資料型別

  • 使用 & 來串連字串:

    MsgBox("hello" & vbCrLf & "goodbye")
    
  • 若要在迴圈 (Loop) 中附加字串,請使用 StringBuilder 物件:

    Dim longString As New System.Text.StringBuilder
    For count As Integer = 1 To 1000
      longString.Append(count)
    Next
    

型別推斷

善加利用區域變數的型別推斷:

Public Sub GetQuery()
  Dim filterValue = "London"
  Dim query = From customer In customers 
              Where customer.Country = filterValue
End Sub

事件處理常式中比較不嚴謹的委派

如果您不要在程式碼中使用事件引數,請使用比較不嚴謹的委派 (Delegate) 並省略事件引數:

Public Sub Form1_Load() Handles Form1.Load
End Sub

不帶正負號的資料型別

  • 使用 Integer,而非不帶正負號的型別,除非是針對記憶體有限的情況。

陣列

  • 在宣告行上初始化陣列時,請使用短語法:

    Dim letters1() As String = {"a", "b", "c"}
    

    而不是:

    Dim letters2() As String = New String() {"a", "b", "c"}
    
  • 將陣列指示項放在變數上,不要放在型別上:

    Dim letters3() As String = {"a", "b", "c"}
    

    而不是:

    Dim letters4 As String() = {"a", "b", "c"}
    
  • 在宣告和初始化基本資料型別的陣列時,請使用 { } 語法:

    Dim letters5() As String = {"a", "b", "c"}
    

    而不是:

    Dim letters6(2) As String
    letters6(0) = "a"
    letters6(1) = "b"
    letters6(2) = "c"
    

使用 With 關鍵字

對一個物件使用一連串的呼叫時,請考慮使用 With 關鍵字:

With orderLog
  .Log = "Application"
  .Source = "Application Name"
  .MachineName = "Computer Name"
End With

在 For 或 For Each 陳述式中使用迴圈變數的型別推斷

讓型別推斷來判斷迴圈範圍變數的型別。

下列是在 For 陳述式中使用型別推斷的範例:

For count = 0 To 2
  MsgBox(names(count))
Next

下列是在 For Each 陳述式中使用型別推斷的範例:

For Each name In names
  MsgBox(name)
Next

使用 Try...Catch 和 Using 陳述式處理例外狀況

  • 不要使用 On Error Goto。

  • 若要處理例外狀況,請使用 Try...Catch 陳述式:

    Dim conn As New SqlConnection("connection string")
    Try
      Conn.Open()
    Catch ex As SqlException
    
    Finally
      Conn.Close()
    End Try
    
  • Using 陳述式將 Try...Catch 陳述式與 Dispose 方法的呼叫結合在一起,以簡化程式碼。 如果您要使用 Try...Catch 陳述式,而且 Finally 區塊中的唯一程式碼是 Dispose 方法的呼叫,請改用 Using 陳述式:

    Using redPen As New Pen(color.Red)
      ' Insert code here.
    End Using
    

使用 IsNot 關鍵字

優先使用 IsNot 關鍵字,而非 Not...Is Nothing。

使用 AndAlso 和 OrElse 關鍵字

在執行比較時,若要略過不必要的程式碼以避免例外狀況並提升效能,請使用 AndAlso 代替 And 並使用 OrElse 代替 Or:

' Avoid a null reference exception. If the left side of the AndAlso 
' operator is False, the right side is not evaluated and a null 
' exception is not thrown.
If nullableObject IsNot Nothing AndAlso nullableObject = testValue Then

End If

' Avoid an unnecessary resource-intensive operation. If the left side
' of the OrElse operator is True, the right side is not evaluated and 
' a resource-intensive operation is not called.
If testCondition OrElse ResourceIntensiveOperation() Then

End If

表單的預設執行個體

使用 Form1.ShowDialog,而非 My.Forms.Form1.ShowDialog。

New 關鍵字

  • 使用短的執行個體化 (Instantiation):

    Dim employees As New List(Of String)
    

    前一行等於:

    Dim employees2 As List(Of String) = New List(Of String)
    
  • 為新物件使用物件初始設定式,代替無參數的建構函式 (Constructor):

    Dim orderLog As New EventLog With { 
        .Log = "Application", 
        .Source = "Application Name", 
        .MachineName = "Computer Name"}
    

事件處理

  • 使用 Handles,而非 AddHandler:

    Private Sub ToolStripMenuItem1_Click() Handles ToolStripMenuItem1.Click
    End Sub
    
  • 使用 AddressOf,且不要明確地對委派 (Delegate) 執行個體化。

    Dim closeItem As New ToolStripMenuItem( 
        "Close", Nothing, AddressOf ToolStripMenuItem1_Click)
    Me.MainMenuStrip.Items.Add(closeItem)
    
  • 當您定義事件時,請使用短語法並且讓編譯器定義委派:

    Public Event WhatHappened(ByVal source As Object, 
                              ByVal e As WhatHappenedEventArgs)
    
  • 在呼叫 RaiseEvent 方法之前,不要檢查事件是否為 Nothing (null)。 RaiseEvent 會在引發事件之前檢查 Nothing。

使用共用成員

使用類別名稱呼叫 Shared 成員,而不要從執行個體變數進行呼叫。

使用 MsgBox 函式

使用 MsgBox,取代 MessageBox.Show 或 Console.WriteLine。 在不支援 MsgBox 函式 (例如 Silverlight) 的環境中,請使用適合的替代方案。

使用 My 命名空間

優先使用 My 功能,而非 .NET Framework 類別庫 (Class Library) 或 Visual Basic 執行階段程式庫。 如需詳細資訊,請參閱物件 (Visual Basic)

使用 XML 常值

XML 常值 (Literal) 會簡化在您使用 XML 時所遇到的最常見工作 (例如載入、查詢和轉換)。 當您以 XML 進行開發時,請遵循下列方針:

  • 使用 XML 常值建立 XML 文件和片段,而不要直接呼叫 XML API。

  • 在檔案或專案等級匯入 XML 命名空間,以充分利用 XML 常值的效能最佳化。

  • 使用 XML 軸屬性 (Property) 存取 XML 文件中的項目和屬性 (Attribute)。

  • 使用內嵌運算式,以加入值並從現有值建立 XML,而不要使用如 Add 方法之類的 API 呼叫:

    Private Function GetHtmlDocument( 
        ByVal items As IEnumerable(Of XElement)) As String
    
      Dim htmlDoc = <html>
                      <body>
                        <table border="0" cellspacing="2">
                          <%= 
                            From item In items 
                            Select <tr>
                                     <td style="width:480">
                                       <%= item.<title>.Value %>
                                     </td>
                                     <td><%= item.<pubDate>.Value %></td>
                                   </tr> 
                          %>
                        </table>
    
                      </body>
                    </html>
    
      Return htmlDoc.ToString()
    End Function
    

LINQ 查詢

  • 使用有意義的名稱做為查詢變數的名稱:

    Dim seattleCustomers = From cust In customers 
                           Where cust.City = "Seattle"
    
  • 在查詢中使用別名項目,以確保匿名型別的屬性名稱大寫採用正確的 Pascal 大小寫:

    Dim customerOrders = From customer In customers 
                         Join order In orders 
                           On customer.CustomerID Equals order.CustomerID 
                         Select Customer = customer, Order = order
    
  • 當結果中的屬性名稱會變成模稜兩可時,請重新命名屬性。 例如,如果您的查詢傳回客戶名稱和訂單 ID,請不要保留為結果中的 Name 和 ID,而是加以重新命名:

    Dim customerOrders2 = From cust In customers 
                          Join ord In orders
                            On cust.CustomerID Equals ord.CustomerID 
                          Select CustomerName = cust.Name, 
                                 OrderID = ord.ID
    
  • 在查詢變數和範圍變數的宣告中使用型別推斷:

    Dim customerList = From cust In customers
    
  • 將查詢子句對齊在 From 陳述式下方:

    Dim newyorkCustomers = From cust In customers 
                           Where cust.City = "New York" 
                           Select cust.LastName, cust.CompanyName
    
  • 將 Where 子句使用在其他查詢子句之前,以確保後來的查詢子句會在已縮減且篩選過的資料集上運作:

    Dim newyorkCustomers2 = From cust In customers 
                            Where cust.City = "New York" 
                            Order By cust.LastName
    
  • 使用 Join 子句明確定義聯結 (Join),而不要使用 Where 子句隱含定義聯結:

    Dim customerList2 = From cust In customers 
                        Join order In orders 
                          On cust.CustomerID Equals order.CustomerID 
                        Select cust, order
    

使用 Visual Basic 執行階段程式庫成員

優先使用 Visual Basic 執行階段程式庫,而非 .NET Framework 類別庫。

請參閱

概念

安全程式碼撰寫方針

其他資源

開發類別庫的設計方針