VB.NET 与 .NET 的关系

很多人把 Visual Basic 和“上世纪的老 VB”混为一谈。今天真正在用的是 VB.NET:它不再是独立的语言环境,而是和 C# 一样编译成中间语言、运行在 .NET 之上的第一等公民。也就是说,同一个 .NET 类库、同一套运行时、同一份垃圾回收机制,只是写法的“语法糖”不同。

VB.NET 的定位很清晰:语法接近自然语言(If ... Then、For Each、End Sub),配合 Visual Studio 的窗体设计器可以拖拽出界面,非常适合入门教学、内部工具和以 Windows 桌面为目标的小型应用。理解了“它只是 .NET 上的一种语言”,你就明白为什么这段 VB 代码可以调用任何 C# 写的库。

选语言前先问“要解决什么问题”。VB.NET 的强项是低门槛的 Windows 桌面工具;若目标是跨平台服务端或高性能计算,C# 与 C++ 会更合适。
本文核心知识点
  • 同一运行时VB.NET 与 C# 共用 .NET 类库与 CLR,能力对等。
  • 事件驱动界面程序靠事件回调驱动,而不是顺序执行。
  • 窗体与控件拖拽式设计器生成界面代码,Handles 绑定事件。
  • Option Strict打开后强制显式类型转换,能提前发现大量错误。
Visual Basic 可视化窗体开发示意:悬浮窗体面板由工具箱方块拼装,带网格对齐线与控件图标
窗体设计器把“界面”变成可拖拽的积木:摆好控件,再为它们写事件处理逻辑。

语法入门:变量、条件与循环

VB.NET 用 Dim 声明变量,用 As 指定类型。它默认允许隐式类型转换(Option Strict Off),为了代码健壮,建议每个文件顶部都写上 Option Strict On 与 Option Explicit On,让编译器把危险的隐式转换拦下来。

Option Strict On
Option Explicit On

Module Program
    Sub Main()
        Dim name As String = "VB.NET"
        Dim score As Integer = 87

        If score >= 90 Then
            Console.WriteLine("优秀")
        ElseIf score >= 60 Then
            Console.WriteLine($"及格,分数 {score}")
        Else
            Console.WriteLine("需要加油")
        End If

        For i As Integer = 1 To 3
            Console.WriteLine($"{name} 第 {i} 次")
        Next

        Dim total As Integer = 0
        Dim nums() As Integer = {3, 6, 9}
        For Each n In nums
            total += n
        Next
        Console.WriteLine($"合计 = {total}")     ' 18
    End Sub
End Module

几个与 C 系语言不同的点值得记牢:字符串拼接用 &(虽然 + 也能用,但对字符串更推荐 &);注释用单引号 ';字符串插值同样是 $"...";不区分大小写,但编辑器会自动帮你规范大小写。

面向对象:类与模块

VB.NET 的面向对象能力与 C# 相当:有类、继承、接口、属性与构造函数,只是关键字更“拟人化”——继承用 Inherits,实现接口用 Implements,重写用 Overrides。属性通过 Property 声明,可读可写由 Get / Set 决定。

Option Strict On

Public Class Rectangle
    Public Property Width As Double
    Public Property Height As Double

    Public Sub New(w As Double, h As Double)
        Width = w
        Height = h
    End Sub

    Public Function Area() As Double
        Return Width * Height
    End Function
End Class

Module Program
    Sub Main()
        Dim r As New Rectangle(3.0, 4.0)
        Console.WriteLine($"面积 = {r.Area()}")   ' 12
    End Sub
End Module

Module 里放的成员是全局可直接调用的过程(类似“静态类的语法糖”),适合放入口点与工具函数;真正的业务数据应该用 Class 封装。养成“数据进类、逻辑进方法”的习惯,代码才容易维护和测试。

Windows 窗体:拖拽出你的界面

Windows 窗体(WinForms)是 VB.NET 最经典的开发方式:在 Visual Studio 里新建一个“Windows 窗体应用”,就能看到设计视图与工具箱,把按钮、文本框、标签拖到窗体上,调整大小与位置,界面的初始化代码由设计器自动生成(存放在 .Designer.vb 中,一般不要手改)。

控件用途最常用事件
Button触发动作Click
TextBox输入与显示文本TextChanged
Label显示说明或结果—
ComboBox下拉选择SelectedIndexChanged
ListBox列出多项数据SelectedIndexChanged
Timer定时触发Tick

每个控件的名称(Name)很有讲究:btnConvert、txtCelsius、lblResult 这样的前缀命名,能让代码里的引用一目了然。设计器只负责“长什么样”,真正的行为都要在事件处理过程里写。

事件驱动:按钮点击之后发生了什么

窗体程序不像控制台那样从头到尾顺序执行,而是启动后就进入消息循环,等待用户操作。用户点击按钮时,系统把“点击”这个事件派发给已注册的处理过程。VB.NET 用 Handles 关键字把过程与事件绑定,这是它相比其他语言最直观的地方。

Option Strict On

Public Class Form1
    Private Sub btnHello_Click(sender As Object, e As EventArgs) Handles btnHello.Click
        Dim who As String = txtName.Text.Trim()
        If who = "" Then
            MessageBox.Show("请先输入名字")
            Return
        End If
        lblGreeting.Text = $"你好,{who}!"
    End Sub
End Class

关键在于最后那句 Handles btnHello.Click:它告诉运行时“当 btnHello 被点击时调用这个过程”。一个过程可以同时 Handles 多个事件(用逗号分隔),也可以通过 AddHandler 在运行时动态绑定。理解“事件—处理过程”这条链路,就理解了所有 GUI 框架的共同骨架。

数据绑定与文件读写

界面与数据脱节是新手代码变乱的开始。WinForms 提供了数据绑定:把控件属性的值与一个数据源关联,数据变化会自动反映到界面。对于入门的字典/列表,也可以直接 For Each 填进 ListBox;更规范的写法是用 BindingList 或 DataTable 作为数据源。

Imports System.IO

Public Class Form1
    Private Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
        If Not File.Exists("names.txt") Then
            MessageBox.Show("找不到 names.txt")
            Return
        End If

        lstNames.Items.Clear()
        For Each line In File.ReadAllLines("names.txt")
            If line.Trim() <> "" Then lstNames.Items.Add(line.Trim())
        Next
    End Sub

    Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
        Dim lines() As String = lstNames.Items.Cast(Of Object)() _
                                         .Select(Function(x) x.ToString()).ToArray()
        File.WriteAllLines("names.txt", lines)
        MessageBox.Show("已保存")
    End Sub
End Class

文件读写时注意“用完即关”——File.ReadAllLines / File.WriteAllLines 这类静态方法内部已帮你打开与关闭句柄,适合小文件;处理大文件则用 Using 块配合 StreamReader,保证异常时资源也能释放。