VB.NET 與 C# 共享同一個 CLR、BCL、JIT 編譯器,最終皆編譯為 MSIL。語言差異本質上是編譯器提供的語法糖與預設行為不同。本文依據 .NET Framework 2.0 (VS2005) 至 4.0 (VS2010) 版本演進,系統性對比雙語言功能缺口。
| 功能 | VB.NET | C# | 備註 |
|---|---|---|---|
| 區域靜態變數 | ✅ Static | ❌ (需靜態欄位模擬) | VB 保留 VB6 相容特性 |
| WithEvents / Handles | ✅ 編譯器自動掛接事件 | ❌ 手動 += | VB 事件處理極便利 |
| 選用參數 | ✅ Optional | ❌ (C# 4.0 才支援) | C# 早期用多載模擬 |
| 具名參數 | ✅ | ❌ (C# 4.0 才支援) | |
| 屬性參數 (Property Parameters) | ✅ Property Item(index As Integer) As String | ✅ 索引子 this[int index] | 語法不同,功能等價 |
| 非虛擬呼叫虛擬方法 | ✅ MyBase.Method() | ❌ 需 base.Method() 但僅限建構函式/覆寫中 | VB 更靈活 |
| 重新命名實作介面 | ✅ Implements IFoo.Method | ❌ 顯式介面實作 void IFoo.Method() | VB 可不同名 |
| 晚期繫結 | ✅ Option Strict Off | ❌ (C# 4.0 dynamic) | VB 傳統優勢 |
| With 陳述式 | ✅ With obj ... End With | ❌ | 語法糖,IL 等價 |
| Imports 靜態成員 | ✅ Imports System.Math | ❌ (C# 6.0 using static) | |
| 模組 | ✅ Module (隱含 Shared) | ❌ static class | VB 模組 = C# 靜態類別 |
| Is 運算子 | ✅ 參考比較 | ❌ (用 ReferenceEquals) | |
| Try...Catch When | ✅ 例外過濾器 | ❌ (C# 6.0 when) | VB 早 10 年支援 |
| VB Runtime Library | ✅ Microsoft.VisualBasic | ❌ | 字串、檔案、互動函數豐富 |
| 運算子多載 | ❌ (VB 10 / VS2010 才支援) | ✅ 早期支援 | C# 傳統優勢 |
| Event Add/Remove 存取子 | ❌ (VB 10 才支援) | ✅ | |
| using 陳述式 | ❌ (VB 用 Using...End Using) | ✅ | 語法不同,語意同 |
| XML 文件註解 | ❌ (VB 9 / VS2008 才支援) | ✅ /// | C# 早期佔優 |
| Unsafe / Pointer | ❌ | ✅ unsafe | C# 獨有 |
| as 運算子 | ❌ (用 TryCast) | ✅ | |
| out 參數 | ❌ (用 ByRef) | ✅ | 語意不同 |
| 編譯器 CLS 檢查 | ❌ | ✅ /clscompliant | |
| 迭代器 | ❌ (VB 12 / VS2013 Yield) | ✅ yield return | |
| 匿名方法 | ❌ (VB 9 Lambda) | ✅ C# 2.0 | |
| 預設實例 | ✅ Form1.Show() | ❌ | VB 獨有 (爭議特性) |
| My 命名空間 | ✅ My.Computer, My.Settings | ❌ | VB 獨有生產力工具 |
' VB.NET - 聲明即掛接,零樣板碼
Public WithEvents btn As Button
Private Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
MessageBox.Show("Clicked")
End Sub
// C# - 需手動訂閱
button.Click += (s, e) => MessageBox.Show("Clicked");
// 或
button.Click += Btn_Click;
void Btn_Click(object s, EventArgs e) { ... }
VB 編譯器在建構函式自動生成 AddHandler 程式碼,大幅減少樣板碼與記憶體洩漏風險 (忘記 -=)。
' VB.NET - Catch When 精準捕捉
Try
RiskyOperation()
Catch ex As IOException When ex.HResult = -2147024864 ' FILE_NOT_FOUND
Log("File missing")
Catch ex As IOException
Log("Other IO error")
End Try
// C# 6.0 前只能捕捉後再判斷
try { RiskyOperation(); }
catch (IOException ex) when (ex.HResult == -2147024864) { Log("File missing"); }
catch (IOException ex) { Log("Other IO error"); }
My.Computer.FileSystem、My.Settings、My.Resources、My.Application、My.User、My.WebServices — 為常見工作提供強型別、IntelliSense 友善的捷徑,C# 需自行呼叫 ConfigurationManager、File 等分散 API。
// C# - 互操作、高效能陣列操作、系統程式
unsafe void FastCopy(byte[] src, byte[] dst, int count)
{
fixed (byte* pSrc = src, pDst = dst)
{
for (int i = 0; i < count; i++) pDst[i] = pSrc[i];
}
}
VB.NET 設計哲學排除指標,若需高效能互操作需透過 P/Invoke 或 C# 協助類別庫。
| 功能 | VB.NET | C# | 備註 |
|---|---|---|---|
| 記錄類型 | ❌ | ✅ record | C# 9+ |
| 模式比對 | ❌ | ✅ switch, is, and/or/not | C# 7+ |
| 全域 Using | ❌ | ✅ global using | C# 10+ |
| 原始碼產生器 | ❌ | ✅ | C# 生態主導 |
| Nullable 參考型別 | ❌ | ✅ #nullable enable | C# 8+ |
| 檔案範圍命名空間 | ❌ | ✅ namespace N; | C# 10+ |
| 必要成員 | ❌ | ✅ required | C# 11+ |
| 主建構函式 | ❌ | ✅ class C(int X) | C# 12+ |
| 集合運算式 | ❌ | ✅ [1,2,3] | C# 12+ |
現代 .NET 團隊將語言創新資源高度集中於 C#,VB.NET 進入「維護模式」:僅修復 Bug、支援新平台,不再添加新語言特性。
| 場景 | 推薦語言 | 理由 |
|---|---|---|
| 新專案、微服務、雲原生、高效能庫 | C# | 語言特性豐富、生態主導、人才庫大、效能調優工具完善 |
| 維護舊 VB.NET 專案、WinForms 業務系統快速開發 | VB.NET | My 命名空間、WithEvents、預設實例、VB Runtime 仍具生產力優勢 |
| 團隊技能單一、跨語言協作 | 統一 C# | 降低認知負荷、程式碼審查一致性、招聘容易 |
VB.NET 與 C# 的功能差距,本質上反映了語言設計哲學分歧:VB 著重「業務邏輯表達直觀、樣板碼最少、對遷移者友善」;C# 著重「通用程式設計表達力、型別系統嚴謹、演進激進」。在 .NET Core 統一執行階段後,兩語言互通性完美 (同 IL、同 BCL),選擇哪一門純粹取決於團隊歷史資產與未來技術棧規劃。