VB.NETからC#へ完全移行ガイド|Visual Studio 2022で使える変換ツール・手順・落とし穴と対策

VB.NET から C# へ移行したいのに、Visual Studio 2022 に純正コンバータが見つからない――これは多くの現場で直面する課題です。本記事では、実務で再現性の高い変換フローとツール選定、WinForms/WPF 特有の落とし穴、VB と C# の言語差分の埋め方までを網羅。拡張機能・オンライン・商用・AI をどう使い分けるかを具体的に示します。

目次

結論と前提:Visual Studio 2022 に「純正の VB→C# 一括変換」はない

Visual Studio 2022(Community を含む)には、ソリューション/プロジェクト/ファイル単位で VB.NET コードを C# に自動変換する標準機能は提供されていません。したがって、現実解は 拡張機能(Code Converter)+人手修正+テストをセットにしたワークフローを設計し、プロジェクト特性に応じて オンライン変換・商用ツール・AI を補助輪として使い分けることです。

質問概要(要約)

「Visual Studio 2022 Community Edition に VB→C# の組み込みコンバータが見当たらない。以前試したサードパーティー拡張の品質が低く所在も不明。標準機能は削除されたのか? 代替ツールや推奨手順を知りたい」

回答・解決策:目的別ツール選定

目的推奨ツール/方法メモ(補足・注意点)
無償で VS 内で一括変換Code Converter(SharpDevelopTeam.CodeConverter)
Visual Studio の「拡張機能」からインストール → ソリューション/プロジェクト/ファイルを右クリック → Convert to C#
Microsoft 製ではないオープンソース拡張。Roslyn ベースで保守的な変換を行い、実務での利用実績が豊富。
オンラインで部分コードを変換Telerik Code Converter(Web)、ICSharpCode Code Converter(Web)短い断片の比較や「この構文はどうなる?」の確認に最適。プロジェクト変換の検証用に。
別 IDE でプロジェクト単位変換SharpDevelop(旧 IDE)レガシーだが大規模変換の成功例あり。現行 .NET との互換は要注意・要検証。
精度重視の商用製品tangible VB to C# Converter などGUI と差分ビューが充実。予算が許すなら最短で収束しやすい。試用版で品質を先に評価。
AI に頼るChatGPT などの LLM関数単位・ファイル単位での翻訳に有効。動作保証はしないため、型・例外・イベントの差分は必ず人手で確認。

変換が不要な戦略も検討

  • 既存資産が .NET Framework 4.8 で安定稼働しているなら、まずは VB のまま運用を継続し、外縁(新規機能)を C# で実装していく サイドバイサイド戦略が堅実。
  • 共通ライブラリから先に C# 化して参照先を段階的に差し替えると、影響範囲を制御しやすい。

変換前チェックリスト(品質を左右する事前整備)

項目狙い具体策
ビルドの健全化変換起因のエラーを正しく切り分け警告を極力 0 に近づけ、単体テストを緑に。未使用参照・デッドコードを削除。
VB 言語オプションの固定挙動の再現性を担保Option Strict On、Option Infer On、Option Explicit On を徹底。
依存関係の棚卸し移行可否の判断COM、レガシー WebForms、XML リテラル、Microsoft.VisualBasic 依存の把握。
資産の分割段階移行UI/ドメイン/データアクセスを分離。まずドメイン層から C# 化。
バックアップとブランチ戦略リスク低減変換専用ブランチを作成。git tag で変換前のスナップショットを保存。

推奨ワークフロー(Code Converter 中心)

  1. 現行の VB プロジェクトを正常ビルド(テスト緑、警告極小化)。
  2. Code Converter を導入(Visual Studio の「拡張機能」から検索)。ソリューション/プロジェクト/ファイル単位で Convert to C# を実行。
  3. ビルド&修正のループ。WinForms/WPF の Designer 生成コード、My 名前空間、WithEvents、Handles、暗黙の数値変換などを重点的に解消。
  4. ユニットテストと手動テストを実施。UI 操作、文化依存の文字列比較、時刻・小数の丸めに注意。
  5. コード規約の整形とリファクタリング(nullable 対応、var/式本体メンバー、switch 式ほか)。
  6. アナライザ/フォーマッタ(Roslyn アナライザ、StyleCop、dotnet format)で静的品質を担保。
  7. 最終的に .NET Upgrade Assistant により .NET 6/8 への移行も検討。

プロジェクト種類別の重要ポイント

Windows Forms

  • Designer 生成コード(*.Designer.vb)は C# では *.Designer.cs に。Partial の分割と InitializeComponent() の整合を確認。
  • イベント配線:VB の Handles は C# では += で明示的に購読が必要。
  • My.Application の単一インスタンス機能は WindowsFormsApplicationBase 相当。C# では明示実装か代替パターンに置換。
  • リソース(My.Resources)は Properties.Resources にマップ。

WPF

  • XAML のコードビハインド型名、名前空間、x:Class の一致を必ず確認。
  • イベント属性は C# メソッド署名に合わせて再配線。RoutedEvent のバブリング処理はそのまま。
  • My.Settings は Properties.Settings.Default 経由に置換。

クラスライブラリ/コンソール

  • 参照の差し替えが容易。まずここから C# 化して上位層へ波及させるのが定石。
  • 暗黙の数値変換と日付の既定値(Date)に注意。

言語差分の「躓きどころ」マッピング

VB.NETC#ポイント
WithEvents + Handlesevent += handler;自動配線が消える。手動で購読を追加。
RaiseEvent E(args)E?.Invoke(this, args);ヌル条件演算子でスレッドセーフに。
Modulestatic class全メンバー static。名前衝突に注意。
Default プロパティインデクサ this[ ]既定プロパティは C# のインデクサへ。
Optional 引数既定値付き引数コンパイル時定数のみ。参照型は注意。
ByRefref/out代入の有無で out を選択。
暗黙の数値変換明示キャスト狭い型への代入はコンパイルエラー。
AndAlso/OrElse&&/||短絡評価は同じ。
IIf(a,b,c) / If(a,b)cond ? b : c / a ?? bIIf は常に両方評価に注意。
Nothingnull値型では既定値。C# は default。
DirectCast/TryCast(T)/asas は失敗で null。
Like 演算子正規表現 or StartsWith 等互換 API か置換。文化差に注意。
ReDim PreserveArray.Resizeコレクションへ置換が推奨。
Option Compare TextStringComparisonOrdinal/InvariantCultureIgnoreCase を明示。
XML リテラルXDocument/XElementリテラル構文は不可。LINQ to XML へ。
My.Settings/My.ResourcesProperties.Settings/Properties.Resources自動生成の名前空間が変わる。
On Error Resume Nexttry { } catch { }構造化例外へ全面置換。

代表的な書き換え例

WithEvents / Handles → 明示購読

' VB
Public Class Form1
  Private WithEvents _t As System.Timers.Timer
  Private Sub Form1_Load(...) Handles MyBase.Load
    _t = New System.Timers.Timer(1000)
    _t.AutoReset = True
    _t.Enabled = True
  End Sub
  Private Sub T_Elapsed(sender As Object, e As Timers.ElapsedEventArgs) Handles _t.Elapsed
    Debug.Print("tick")
  End Sub
End Class
// C#
public partial class Form1 : Form
{
    private System.Timers.Timer _t;
    public Form1()
    {
        InitializeComponent();
        _t = new System.Timers.Timer(1000) { AutoReset = true, Enabled = true };
        _t.Elapsed += T_Elapsed; // 明示的に購読
    }
    private void T_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        => System.Diagnostics.Debug.WriteLine("tick");
}

Default プロパティ → インデクサ

' VB
Default Public Property Item(index As Integer) As String
  Get : Return _list(index) : End Get
  Set(value As String) : _list(index) = value : End Set
End Property
// C#
public string this[int index]
{
    get => _list[index];
    set => _list[index] = value;
}

Optional 引数/IIf/null 合体

' VB
Sub Log(msg As String, Optional level As Integer = 1)
Dim y = IIf(flag, 10, 0)
Dim len = If(name, "").Length
// C#
void Log(string msg, int level = 1) { /* ... */ }
var y = flag ? 10 : 0;
var len = (name ?? string.Empty).Length;

Late Binding(Option Strict Off)→ dynamic / 明示型

' VB
Option Strict Off
Dim o As Object = GetSomething()
o.Foo(123)
// C#
dynamic o = GetSomething();
o.Foo(123); // 例外は実行時に発生しうる。可能ならインターフェイス化。

My 名前空間の置換ガイド

VB(My.*)C# の代表置換備考
My.Applicationエントリポイント(Program.cs)や ApplicationConfiguration.Initialize()単一インスタンス等は明示実装へ。
My.SettingsProperties.Settings.Default型付設定は自動生成。
My.ResourcesProperties.Resourcesリソース名の相違に注意。
My.Computer.FileSystemSystem.IO(または Microsoft.VisualBasic.FileIO を直接利用)互換 API を使うか .NET 標準 IO に寄せる。

プロジェクトファイル(SDK スタイル)への整備例

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="x.y.z" PrivateAssets="all" />
    <PackageReference Include="StyleCop.Analyzers" Version="x.y.z" PrivateAssets="all" />
  </ItemGroup>
</Project>

コード規約と自動整形(.editorconfig の一例)

root = true

[*.cs]
dotnet_diagnostic.IDE0005.severity = warning
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_require_accessibility_modifiers = always:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
csharp_style_namespace_declarations = file_scoped:suggestion 

テスト観点と品質ゲート

  • 境界値と文化差:文字列比較は StringComparison を明示(推奨:Ordinal)。
  • 日時・小数:丸め・書式・タイムゾーンの明示的指定(InvariantCulture)。
  • イベント:購読漏れ/二重購読を単体テストで検知(ハンドラ呼び出し回数の検証)。
  • 静的解析:アナライザの警告 0 を継続的に維持。CI で dotnet build -warnaserror。

トラブルシューティング(実務で頻出)

  • 「型 ‘Microsoft.VisualBasic.…’ が見つかりません」:暫定対応として NuGet/参照追加で解決可能だが、長期的には .NET 標準 API に寄せて依存排除。
  • Designer が壊れる/イベントが動かない:InitializeComponent() での += 配線漏れを確認。Modifiers の可視性も要チェック。
  • 数値の切り捨て/丸めが変わった:VB の暗黙変換を明示化。Convert 系か Math に統一。
  • 文字列比較で想定外:VB の Option Compare Text を使っていた場合、C# では既定が Ordinal。明示指定に置換。
  • XML リテラルが使われていた:LINQ to XML(XDocument/XElement)へ全面移行。

AI の活用ポイント

  • 変換器が苦手な構文(XML リテラル、WithEvents、Like、On Error)は、意図を説明しながら AI に段階的な置換案を出させ、最終コードは人間が確定。
  • PR レビューの補助として差分に対する説明生成を活用。テスト観点の列挙にも有効。

移行の見積もりと進め方(実践モデル)

概算は 変換対象 LoC × 0.8〜1.2 分/行 + UI 再配線工数 + テスト工数 が目安。WinForms/WPF を大量に含む場合は UI 再配線がボトルネックとなるため、フォーム単位でスプリント化し、毎スプリントで動く成果物を出すことが成功の鍵です。

最小のリスクで価値を出す順序

  1. 非 UI のドメイン/ユーティリティから C# 化。
  2. ViewModel(WPF)や Presenter(WinForms)へ波及。
  3. 最後に View(フォーム/XAML)を置換。

覚えておきたい C# 近代機能での「前向き置換」

  • null 許容参照型(Nullable=enable):NRE の温床を事前に警告化。
  • パターンマッチング:switch 式や型パターンで VB の分岐を簡潔に。
  • レコード:不変 DTO を簡潔に表現。VB の Structure 代替としても検討。
  • file-scoped namespace:ボイラープレート削減。

サイドバイサイド戦略の運用ヒント

  • ソリューション内に *.vbproj と *.csproj を混在させても問題ありません。段階的に参照先を C# 実装へ差し替え。
  • 共通インターフェイスで両言語実装を差し替え可能に。UI 層からの利用は IF 経由に固定。
  • 共有テストで動作一致を担保(同じテストを VB 実装/C# 実装に当てる)。

FAQ(よくある質問)

Q. 自動変換だけで完了できますか?
A. できません。イベント配線、暗黙変換、My 依存などは人手修正が必須です。

Q. Microsoft.VisualBasic 参照は残してもよい?
A. 短期的には可。ただし長期的には標準 API へ置換推奨(学習コスト、将来メンテを低減)。

Q. 商用コンバータを使う価値は?
A. UI サポートや差分管理が強力で、総工数を圧縮できるケースが多い。まずは試用評価を。

Q. 変換後に .NET も上げるべき?
A. 互換性とライブラリ事情次第。まずは同等のランタイムで動作を再現し、その後 Upgrade Assistant で段階的に上げるのが安全です。

まとめ(要点)

  • Visual Studio 2022 に純正の VB→C# 一括変換はない。Code Converter が事実上の標準。
  • 「自動変換 → 人手修正 → テスト → リファクタリング」の反復が王道。
  • WinForms/WPF の イベント配線・Designer・My 名前空間を最優先で確認。
  • 言語差分(Optional、ByRef、暗黙変換、Like、XML リテラル)を表で潰す。
  • 最終的には .NET 6/8 への移行でメンテ性と将来性を確保。

実務に貼って使えるチェックリスト

タイミングチェックOK 条件
変換前VB プロジェクトが緑(ビルド・テスト)警告 ≦ 10、テスト全緑
変換直後イベント配線・Designer の整合主要画面が起動・操作可能
修正フェーズ暗黙変換/文化依存の除去アナライザ警告 0
リファクタnull 許容・パターンマッチ導入可読性と NRE リスクの低下
最終性能・メモリ・起動時間確認事前ベースライン同等以上

最後に:これだけ覚えておけば外さない

「Code Converter で 7割を機械化し、残り 3割を言語差分表とテストで潰す」。この戦略が最もコスト対効果が高く、多くの現場で成功してきたパターンです。拙速な「全部一気」よりも、スコープを決めた段階移行で確実に価値を積み上げていきましょう。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次