Visual Basic 编码约定

Microsoft 使用这些指南开发示例和文档。 Visual Basic 语言规范并未定义编码标准。

  • 编码约定令代码外观一致,使读者可以将注意力集中在内容而非布局上。

  • 约定能够使读者更快速地理解代码,因为他们可以根据以前的经验作出假设。

  • 约定使复制、更改和维护代码变得更加简单。

  • 约定演示了 Visual Basic 的“最佳做法”。

讨论

命名约定

  • 命名指南在 类库开发的设计准则 中介绍。

  • 您无需为了符合指南而更改由 Visual Studio 设计器工具创建的对象的名称。

  • 使用命名空间限定,而不添加 Imports 语句。 如果在默认情况下将命名空间导入到项目中,则无需完全限定此代码,因为在复制和粘贴此代码时,它将与 IntelliSense 一起以非限定形式运行。 要将长的代码行换行以便于阅读时,可以在“.”后面使限定名换行。例如:

    Dim collection As System.Diagnostics. 
           InstanceDataCollectionCollection
    
  • 请不要在变量名中使用“My”或“my”。 这样会与 My 对象混淆。

布局约定

好的布局通过设置格式,强调代码的结构并使代码更易于阅读。

  • 通过整齐排列功能,用默认设置(智能缩进、4 字符缩进、将制表符保存为空格)对代码的格式进行设置。 有关更多信息,请参见“选项”对话框 ->“文本编辑器”->“Basic”->“VB 专用”

  • 每行仅使用一个语句。 请不要使用 Visual Basic line 行继续符 (:)。

  • 每行仅使用一个声明。

  • 如果整齐排列功能没有设置继续行的格式,则会将连续行缩进一个制表位。

  • 在方法和属性定义之间添加至少一个空白行。

注释约定

  • 不要在代码行的结尾处使用注释。 将注释放在单独行。

  • 注释文本以大写字母开头。

  • 注释以句点结束。

  • 在注释分隔符 (') 和注释文本之间插入一个空格。

    ' Here is a comment.
    
  • 请勿创建已设置格式的将注释包含在内的星号块。

程序结构

  • 在使用 Main 方法时,对新的控制台应用程序使用默认结构,对命令行参数使用 My。

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

语言指南

String 数据类型

  • 使用 & 来连接字符串:

    MsgBox("hello" & vbCrLf & "goodbye")
    
  • 若要将字符串追加到循环,请使用 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

事件处理程序中的宽松委托

如果未在代码中使用事件参数,请使用宽松委托并省略事件参数:

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 关键字

  • 使用短实例化:

    Dim employees As New List(Of String)
    

    下行与上行等效:

    Dim employees2 As List(Of String) = New List(Of String)
    
  • 对于新对象使用对象初始值设定项,而不使用无参数的构造函数:

    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,且不要显式实例化此委托:

    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 类库或 Visual Basic 运行库。 有关更多信息,请参见对象 (Visual Basic)

使用 XML 文本

XML 文本简化了处理 XML 时的最常规任务,例如,加载、查询和转换。 在使用 XML 进行开发时,请遵循下列准则:

  • 使用 XML 文本创建 XML 文档和片段,而不直接调用 XML API。

  • 在文件或项目级别导入 XML 命名空间,以利用 XML 文本的性能优化。

  • 使用 XML 轴属性访问 XML 文档中的元素和特性。

  • 使用嵌入表达式包括值并根据现有的值创建 XML,而不是使用 API 调用(如 Add 方法):

    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 子句显式定义联接,而不是使用 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 类库。

请参见

概念

代码安全维护指南

其他资源

类库开发的设计准则