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 中心)
- 現行の VB プロジェクトを正常ビルド(テスト緑、警告極小化)。
- Code Converter を導入(Visual Studio の「拡張機能」から検索)。ソリューション/プロジェクト/ファイル単位で Convert to C# を実行。
- ビルド&修正のループ。WinForms/WPF の Designer 生成コード、
My名前空間、WithEvents、Handles、暗黙の数値変換などを重点的に解消。 - ユニットテストと手動テストを実施。UI 操作、文化依存の文字列比較、時刻・小数の丸めに注意。
- コード規約の整形とリファクタリング(
nullable対応、var/式本体メンバー、switch式ほか)。 - アナライザ/フォーマッタ(Roslyn アナライザ、StyleCop、
dotnet format)で静的品質を担保。 - 最終的に .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.NET | C# | ポイント |
|---|---|---|
WithEvents + Handles | event += handler; | 自動配線が消える。手動で購読を追加。 |
RaiseEvent E(args) | E?.Invoke(this, args); | ヌル条件演算子でスレッドセーフに。 |
Module | static class | 全メンバー static。名前衝突に注意。 |
Default プロパティ | インデクサ this[ ] | 既定プロパティは C# のインデクサへ。 |
Optional 引数 | 既定値付き引数 | コンパイル時定数のみ。参照型は注意。 |
ByRef | ref/out | 代入の有無で out を選択。 |
| 暗黙の数値変換 | 明示キャスト | 狭い型への代入はコンパイルエラー。 |
AndAlso/OrElse | &&/|| | 短絡評価は同じ。 |
IIf(a,b,c) / If(a,b) | cond ? b : c / a ?? b | IIf は常に両方評価に注意。 |
Nothing | null | 値型では既定値。C# は default。 |
DirectCast/TryCast | (T)/as | as は失敗で null。 |
Like 演算子 | 正規表現 or StartsWith 等 | 互換 API か置換。文化差に注意。 |
ReDim Preserve | Array.Resize | コレクションへ置換が推奨。 |
Option Compare Text | StringComparison | Ordinal/InvariantCultureIgnoreCase を明示。 |
| XML リテラル | XDocument/XElement | リテラル構文は不可。LINQ to XML へ。 |
My.Settings/My.Resources | Properties.Settings/Properties.Resources | 自動生成の名前空間が変わる。 |
On Error Resume Next | try { } 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.Settings | Properties.Settings.Default | 型付設定は自動生成。 |
My.Resources | Properties.Resources | リソース名の相違に注意。 |
My.Computer.FileSystem | System.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 再配線がボトルネックとなるため、フォーム単位でスプリント化し、毎スプリントで動く成果物を出すことが成功の鍵です。
最小のリスクで価値を出す順序
- 非 UI のドメイン/ユーティリティから C# 化。
- ViewModel(WPF)や Presenter(WinForms)へ波及。
- 最後に 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割を言語差分表とテストで潰す」。この戦略が最もコスト対効果が高く、多くの現場で成功してきたパターンです。拙速な「全部一気」よりも、スコープを決めた段階移行で確実に価値を積み上げていきましょう。

コメント