更新: 2008 年 7 月
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 轴属性 (Property) 访问 XML 文档中的元素和属性 (Attribute)。 
- 使用嵌入表达式包括值并根据现有的值创建 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" _ Select cust.LastName, cust.CompanyName
- 使用 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 类库。
示例指南
通用
- 遵循 Design Guidelines for Class Library Developers(类库开发人员设计指南)中的设计指南。 
- 指定 MsgBox 调用的提示和标题。 
- 在适当时使用资源文件。 
- 在每个文件中使用 Option Strict On,或将其用作项目设置。 
- 在编译时打开所有警告。 
- 在一个文件中仅定义一个 Class、Structure 或 Interface。 
- 使用默认编码保存文件。 
本地化
- 在可能的地方使用 AutoSize 属性。 
- 不要隐藏或重叠控件。 
- 不要排列控件以创建语句。 
- 不要通过从另一字符串抽出字符来生成字符串。 
- 使用非特定区域性的图形。 
- 仅使用 Tahoma 或 MS Sans Serif 字体。 
辅助功能
- 使用颜色选取器对话框的“系统”选项卡中的颜色。 
- 为所有菜单、标签和按钮等使用快捷键。 
- 按照下表中的描述设置控件属性。 
| 属性 | 设置 | 
|---|---|
| AccessibleDescription | 控件的描述。 | 
| AccessibleName | 控件名称。 | 
| AccessibleRole | 默认值,如果控件有另一角色,则重置该属性。 | 
| TabIndex | 按逻辑顺序设置。 | 
| Text | 所有可单击的控件都应有一个键盘访问键(快捷键)。 | 
| Font size | 默认值,或设置为 10 磅或以上 | 
| Forecolor | 默认值 | 
| Backcolor | 默认值 | 
| BackgroundImage | 默认值 | 
安全性
遵循代码安全维护指南中的指南。
请参见
其他资源
修订记录
| 日期 | 历史记录 | 原因 | 
|---|---|---|
| 2008 年 7 月 | 更新了指南,现在包括新的语言功能,其中包括 LINQ、XML 文本、对象初始值设定项、类型推断和宽松委托。 | 内容 Bug 修复 |