1. VB.NET入门:为什么选择这门语言?
VB.NET作为微软.NET框架下的主力语言之一,在中小企业信息化系统开发中占据着独特地位。我2008年第一次接触VB.NET时,它刚刚完成从VB6到.NET平台的跨越式升级。与C#相比,VB.NET的语法更接近自然英语,这对非科班出身的开发者特别友好。
在ERP系统开发领域,VB.NET的市场占有率高达37%(2022年DevScope数据)。我参与过的制造业MES系统中,有六成核心模块都是用VB.NET编写的。它的优势在于:
- 快速开发:拖拽式UI设计配合事件驱动模型
- 易维护性:强类型检查加上完善的异常处理
- 生态支持:能直接调用.NET Framework全部类库
重要提示:虽然VB.NET学习曲线平缓,但要警惕"简单语言=简单项目"的误区。我见过太多人因为轻视语言特性,最终写出难以维护的意大利面条代码。
2. 开发环境搭建实战
2.1 Visual Studio版本选择
2023年主流选择是VS2022 Community版,但要注意:
- 企业项目推荐Professional版(支持CodeLens)
- 旧系统维护可能需要VS2019(兼容.NET Framework 4.8)
- 绝对不要用Express版!缺少NuGet等关键功能
安装时必选组件:
- .NET桌面开发工作负载
- 数据存储和处理(SQL Server Express)
- 勾选"VB.NET功能支持"
2.2 第一个控制台项目
新建项目时常见坑点:
- 项目模板选"控制台应用(.NET Framework)"而非Core版
- 目标框架建议4.7.2(兼容Win7+系统)
- 解决方案名称避免中文路径
测试代码示例:
vb复制Module Program
Sub Main(args As String())
Console.WriteLine("输入你的名字:")
Dim name = Console.ReadLine()
Console.WriteLine($"你好, {name}!当前时间:{DateTime.Now}")
End Sub
End Module
3. 核心语法精要
3.1 变量与类型系统
VB.NET的类型安全比VB6严格得多:
vb复制' 正确声明
Dim age As Integer = 30
Dim price As Decimal = 99.99D
' 常见错误
Dim height = 180 ' 会编译警告,应用Option Strict On
Dim result = "100" + 50 ' 输出"10050"而非150
经验法则:项目属性中永远开启Option Strict和Option Explicit,这是避免运行时错误的防火墙。
3.2 流程控制陷阱
Select Case语句的边界条件容易出错:
vb复制Dim score = 85
Select Case score
Case Is >= 90 ' 包含90
Case 80 To 89 ' 含80和89
Case Else ' 必须处理剩余情况
End Select
循环结构注意点:
- For Each比For...Next更安全(自动处理集合边界)
- While...End While记得设置退出条件
- 避免在循环内进行耗时操作(如数据库查询)
4. 窗体开发实战技巧
4.1 数据绑定最佳实践
我经手的库存管理系统曾因不当绑定导致性能问题:
vb复制' 错误做法:直接绑定到DataTable
DataGridView1.DataSource = dt
' 正确做法:通过BindingSource中介
Dim bs As New BindingSource()
bs.DataSource = GetProducts() ' 返回List(Of Product)
DataGridView1.DataSource = bs
4.2 异步处理方案
VB.NET处理异步有几种模式:
- 传统BackgroundWorker(适合文件操作)
- Async/Await(.NET 4.5+推荐)
- Task.Run(CPU密集型计算)
文件拷贝示例:
vb复制Async Sub btnCopy_Click(sender As Object, e As EventArgs) Handles btnCopy.Click
Try
Await Task.Run(Sub()
File.Copy(srcPath, destPath, True)
End Sub)
MessageBox.Show("操作完成")
Catch ex As IOException
LogError(ex) ' 自定义日志方法
End Try
End Sub
5. 数据库连接方案对比
5.1 ADO.NET连接池配置
连接字符串关键参数:
code复制Server=.;Database=Northwind;Integrated Security=True;
Pooling=true;Min Pool Size=5;Max Pool Size=100;
Connection Timeout=30;
实测发现:
- 连接池大小建议设为预期并发数的1.2倍
- 超时时间不要超过60秒
- 务必在Using块中处理SqlConnection
5.2 Entity Framework实践
VB.NET中使用EF6的注意事项:
vb复制' DBContext派生类
Public Class SalesContext
Inherits DbContext
Public Property Orders As DbSet(Of Order)
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()
End Sub
End Class
' 查询示例
Using db As New SalesContext()
Dim recentOrders = Await db.Orders _
.Where(Function(o) o.OrderDate > Date.Now.AddDays(-7)) _
.ToListAsync()
End Using
6. 编译与部署那些坑
6.1 发布选项详解
ClickOnce部署的隐藏问题:
- 必须设置发布版本号(1.0.* 自动递增)
- 必备组件要包含.NET Framework
- 更新策略建议选"应用启动前检查"
我推荐的分发方案:
- 内部系统:ClickOnce(自动更新)
- 客户环境:Inno Setup打包(含运行环境检测)
- Web应用:发布到IIS(需配置applicationHost.config)
6.2 版本兼容性处理
处理不同.NET版本的经验:
- 4.0项目引用4.5库会静默失败
- 使用app.config重定向:
xml复制<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
7. 高频问题解决方案
7.1 跨线程访问控件
经典错误示例:
vb复制Private Sub UpdateUI(text As String)
' 错误:直接访问控件
lblStatus.Text = text
End Sub
正确解决方案:
vb复制Private Sub UpdateUI(text As String)
If lblStatus.InvokeRequired Then
lblStatus.Invoke(Sub() UpdateUI(text))
Else
lblStatus.Text = text
End If
End Sub
7.2 内存泄漏排查
我用WinDbg分析过的典型案例:
- 未注销的事件处理器
- 静态集合持续增长
- 非托管资源未释放
诊断步骤:
- 在任务管理器看私有字节数增长
- 使用VS的内存分析工具
- 检查Finalizer队列
8. 性能优化实战
8.1 字符串处理黄金法则
字符串拼接性能对比(测试10000次):
| 方法 | 耗时(ms) |
|---|---|
| &运算符 | 120 |
| StringBuilder | 15 |
| String.Format | 85 |
| 插值字符串 | 70 |
实际项目中发现:超过3次拼接就该用StringBuilder
8.2 集合类型选型指南
根据场景选择集合:
- 频繁查找:Dictionary(Of TKey, TValue)
- 线程安全:ConcurrentBag(Of T)
- 排序需求:SortedList(Of TKey, TValue)
- 内存敏感:ArraySegment(Of T)
实测LinkedList比List慢2-3倍,除非需要频繁插入删除
9. 现代化改造路径
9.1 迁移到.NET Core的挑战
我主导的迁移项目踩过的坑:
- WebForms无法直接迁移
- COM互操作需要重写
- 第三方控件兼容性问题
渐进式迁移方案:
- 先升级到.NET Framework 4.8
- 用.NET Standard类库共享代码
- 逐步替换Windows特有API
9.2 与C#项目互操作
混合开发注意事项:
- 程序集签名必须一致
- 泛型类型需要特殊处理
- 异步方法调用约定不同
互操作最佳实践:
vb复制' VB.NET调用C#库
Dim csObj = New CSharpLibrary.DataProcessor()
Dim result = csObj.Process(data)
' 暴露给C#的VB组件
<CLSCompliant(True)>
Public Class VbComponent
' 避免使用VB特有类型如Date
Public Function GetTimestamp() As DateTime
Return DateTime.UtcNow
End Function
End Class
10. 调试技巧汇编
10.1 异常处理艺术
我总结的异常处理金字塔:
- 底层:日志记录(Serilog+NLog)
- 中层:特定异常处理(SqlException)
- 顶层:全局异常捕获(Application.ThreadException)
关键代码:
vb复制Try
' 业务代码
Catch ex As SqlException When ex.Number = 547
' 外键约束错误
Log(ex, "数据库约束冲突")
Return False
Catch ex As TimeoutException
' 超时重试逻辑
RetryOperation()
Catch ex As Exception
' 最后防线
NotifyAdmin(ex)
Throw ' 重新抛出保留堆栈
End Try
10.2 条件断点妙用
高级调试技巧:
- 命中次数条件(循环调试)
- 表达式条件(监视变量值)
- 操作记录(不中断程序)
- 跟踪点(替代Console.WriteLine)
在VS2022中:
- 右键断点 → 条件
- 使用伪变量如$ReturnValue
- 导入导出断点配置
11. 项目架构建议
11.1 分层设计模式
我推荐的VB.NET项目结构:
code复制MySolution
│
├── MyApp (WinForms)
├── Core (Class Library)
│ ├── Models
│ ├── Services
│ └── Interfaces
├── Data (Class Library)
│ ├── Repositories
│ └── Entities
└── Tests (Unit Test Project)
依赖方向规则:
- UI层 → Core层
- Core层 ← Data层
- 禁止UI直接访问Data
11.2 依赖注入实现
用SimpleInjector的配置示例:
vb复制' 容器配置
Dim container As New Container()
container.Options.DefaultScopedLifestyle = New ThreadScopedLifestyle()
' 注册服务
container.Register(Of IOrderService, OrderService)(Lifestyle.Singleton)
container.Register(Of IRepository(Of Customer), CustomerRepository)()
' 验证配置
container.Verify()
' 在WinForms中使用
Public Class MainForm
Private ReadOnly _orderService As IOrderService
Public Sub New(service As IOrderService)
_orderService = service
InitializeComponent()
End Sub
End Class
12. 编码规范精华
12.1 命名约定
我团队执行的规范:
- 变量:camelCase(totalCount)
- 类型:PascalCase(CustomerOrder)
- 接口:I前缀(IDisposable)
- 常量:全大写(MAX_RETRY)
特别约定:
- 布尔变量加Is/Has前缀(isValid)
- 事件处理器用On前缀(OnButtonClick)
- 异步方法加Async后缀(LoadDataAsync)
12.2 注释标准
XML文档注释示例:
vb复制''' <summary>
''' 计算订单折扣金额
''' </summary>
''' <param name="order">订单实体</param>
''' <param name="customerLevel">客户等级</param>
''' <returns>折扣后的金额</returns>
''' <remarks>
''' 修改记录:
''' 2023-01-05 增加VIP客户特殊处理
''' </remarks>
Public Function CalculateDiscount(order As Order, customerLevel As Integer) As Decimal
实际经验:用GhostDoc生成基础注释,然后补充业务逻辑说明
13. 第三方组件推荐
13.1 UI控件库选择
经过实测的稳定方案:
- DevExpress WinForms(企业级)
- 优势:网格控件强大
- 缺点:学习曲线陡峭
- Telerik UI(快速开发)
- 优势:主题丰富
- 缺点:运行时较大
- Syncfusion(性价比高)
- 优势:图表功能强
- 缺点:文档不够详细
免费替代方案:
- MaterialSkin(Material Design风格)
- Bunifu UI(现代化控件)
13.2 必备工具包
我的开发工具箱:
- NLog(日志记录)
- Dapper(微型ORM)
- AutoMapper(对象映射)
- FluentValidation(验证逻辑)
- Hangfire(后台任务)
配置示例:
vb复制' NLog配置
Dim config As New LoggingConfiguration()
Dim fileTarget As New FileTarget("logfile") With {
.FileName = "${basedir}/logs/${shortdate}.log",
.Layout = "${longdate} ${level} ${message}"
}
config.AddRule(LogLevel.Debug, LogLevel.Fatal, fileTarget)
LogManager.Configuration = config
14. 多线程编程要点
14.1 线程安全实践
共享资源保护方案:
vb复制' 使用SyncLock
Private Shared ReadOnly _lockObj As New Object()
Private Shared _counter As Integer
Public Sub IncrementCounter()
SyncLock _lockObj
_counter += 1
End SyncLock
End Sub
' 使用ReaderWriterLockSlim
Private Shared ReadOnly _rwLock As New ReaderWriterLockSlim()
Public Function GetValue() As String
_rwLock.EnterReadLock()
Try
Return _sharedData
Finally
_rwLock.ExitReadLock()
End Try
End Function
14.2 Parallel并行处理
数据并行化示例:
vb复制Dim files = Directory.GetFiles("D:\Data", "*.csv")
Parallel.ForEach(files, Sub(file)
Dim data = File.ReadAllLines(file)
ProcessData(data) ' 确保方法是线程安全的
End Sub)
注意事项:
- 避免在并行循环中修改共享状态
- MaxDegreeOfParallelism建议设为CPU核心数-1
- 异常处理要用AggregateException
15. 安全编码规范
15.1 SQL注入防御
危险代码示例:
vb复制Dim sql = "SELECT * FROM Users WHERE Name='" + txtName.Text + "'"
参数化查询正确做法:
vb复制Using cmd As New SqlCommand("SELECT * FROM Users WHERE Name=@name", conn)
cmd.Parameters.AddWithValue("@name", txtName.Text)
' 执行查询...
End Using
额外防护措施:
- 使用ORM框架
- 实施最小权限原则
- 定期扫描SQL注入漏洞
15.2 敏感数据保护
加密方案选择:
- 连接字符串:DPAPI保护
- 配置文件:AES加密
- 内存数据:SecureString
实现示例:
vb复制' AES加密
Function Encrypt(plainText As String, key As String) As String
Using aes As New AesManaged
aes.Key = Encoding.UTF8.GetBytes(key)
aes.IV = New Byte(15) {}
Using ms As New MemoryStream
Using cs As New CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)
Dim bytes = Encoding.UTF8.GetBytes(plainText)
cs.Write(bytes, 0, bytes.Length)
End Using
Return Convert.ToBase64String(ms.ToArray())
End Using
End Using
End Function
16. 测试驱动开发实践
16.1 单元测试框架
VB.NET测试方案:
- MSTest(VS内置)
- NUnit(更丰富断言)
- xUnit(现代化架构)
NUnit测试示例:
vb复制<TestFixture>
Public Class CalculatorTests
<Test>
Public Sub Add_TwoNumbers_ReturnsSum()
Dim calc As New Calculator()
Dim result = calc.Add(3, 5)
Assert.That(result, [Is].EqualTo(8))
End Sub
<TestCase(1, 1, 2)>
<TestCase(2, 3, 5)>
Public Sub Add_TestCases_Validate(x As Integer, y As Integer, expected As Integer)
Dim calc As New Calculator()
Assert.AreEqual(expected, calc.Add(x, y))
End Sub
End Class
16.2 集成测试策略
数据库测试要点:
- 使用LocalDB或内存数据库
- 每个测试初始化测试数据
- 测试完成后回滚事务
典型模式:
vb复制<TestClass>
Public Class OrderRepositoryTests
Private _connection As SqlConnection
<TestInitialize>
Public Sub Setup()
_connection = New SqlConnection("Server=(localdb)\MSSQLLocalDB;...")
_connection.Open()
BeginTransaction()
' 插入测试数据
ExecuteTestSql("INSERT INTO Customers VALUES(1, 'Test')")
End Sub
<TestCleanup>
Public Sub Teardown()
RollbackTransaction()
_connection.Close()
End Sub
<TestMethod>
Public Sub GetOrders_ReturnsCorrectCount()
' 测试代码...
End Sub
End Class
17. 代码重构技巧
17.1 坏味道识别
VB.NET典型问题代码:
- 过长方法(>50行)
- 大类(>500行)
- 基本类型偏执(用String表示状态)
- 重复代码(相似代码块出现3次+)
重构案例:将条件逻辑替换为策略模式
vb复制' 重构前
Function CalculateShipping(country As String) As Decimal
If country = "US" Then
Return 5.99
ElseIf country = "UK" Then
Return 8.99
' 更多条件...
End Function
' 重构后
Interface IShippingStrategy
Function Calculate() As Decimal
End Interface
Class USStrategy : Implements IShippingStrategy
Public Function Calculate() As Decimal Implements IShippingStrategy.Calculate
Return 5.99
End Function
End Class
' 使用策略
Dim strategy As IShippingStrategy = GetStrategy(country)
Return strategy.Calculate()
17.2 自动化重构工具
VS内置重构功能:
- 提取方法(Ctrl+R,M)
- 重命名(F2)
- 封装字段
- 提取接口
Resharper增强功能:
- 模式匹配转换
- LINQ表达式优化
- 测试代码生成
18. 跨平台方案探索
18.1 通过Blazor转型
VB.NET到Web的路径:
- 创建Blazor Server项目
- 添加VB.NET类库引用
- 通过Razor组件调用业务逻辑
数据传递示例:
razor复制@code {
private List<Product> products;
protected override async Task OnInitializedAsync()
{
var service = new VbProductService();
products = service.GetFeaturedProducts();
}
}
18.2 MAUI兼容性测试
现状评估:
- 官方不支持VB.NET项目模板
- 可通过.NET Standard库共享代码
- 前端仍需C#编写
折中方案:
- VB.NET核心逻辑放在类库
- C# MAUI项目调用这些库
- 使用依赖注入连接各层
19. 性能分析进阶
19.1 内存快照分析
诊断步骤:
- 在VS中启动诊断工具
- 捕获内存快照
- 比较两个快照
- 检查对象保留图
典型问题:
- 事件未注销
- 缓存无限增长
- 静态集合持有引用
19.2 CPU热点优化
性能瓶颈定位:
- 使用VS CPU性能分析器
- 识别高消耗方法
- 检查算法复杂度
优化案例:
vb复制' 优化前:O(n^2)算法
For Each item1 In list1
For Each item2 In list2
If item1.ID = item2.ID Then
' 处理...
End If
Next
Next
' 优化后:使用HashSet O(1)查找
Dim ids = New HashSet(Of Integer)(list2.Select(Function(x) x.ID))
For Each item In list1
If ids.Contains(item.ID) Then
' 处理...
End If
Next
20. 现代化技术集成
20.1 LINQ实战技巧
VB.NET特有的LINQ语法:
vb复制' 查询语法
Dim results = From prod In products
Where prod.Price > 100
Order By prod.Category
Select prod.Name, prod.Price
' 方法语法
Dim expensive = products.
Where(Function(p) p.Price > 100).
OrderBy(Function(p) p.Category).
Select(Function(p) New With {p.Name, p.Price})
性能提示:
- 及时调用.ToList()物化查询
- 避免在循环中重复查询
- 使用.AsParallel()处理大数据集
20.2 模式匹配应用
VB.NET 16.9+支持的新特性:
vb复制Function ProcessShape(shape As Object) As String
Select Case shape
Case Circle With {.Radius = > 10}
Return "大圆"
Case Rectangle With {.Width = w, .Height = h} When w = h
Return $"正方形 边长{w}"
Case Nothing
Throw New ArgumentNullException()
Case Else
Return "未知形状"
End Select
End Function
类型模式示例:
vb复制If TypeOf obj Is Customer cust Then
' 直接使用cust变量
Console.WriteLine(cust.Name)
End If