4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

レガシー VB.NET コード対比集(昔こう→今こう)

Last updated at Posted at 2025-12-20

はじめに

これは、Visual Basic Advent Calendar 2025の20日目の記事となります。

400以上のいいねが付いた C# の記事が上がりました。

Visual Basic では、どうなるだろうと思って書いてみます。
C# の元記事を Visual Basic に単純に言語変換できるところは元記事を見ていただき、サポートしていない部分などをチェックしていきます。

処理別リスト

WinForms は除外します。

No. カテゴリ パターン C# (導入) VB.NET 対応状況
1 非同期処理 Begin/End/BackgroundWorker → async/await C# 5.0 / .NET 4.5 VB 2012
2 非同期処理 HttpWebRequest/WebClient → HttpClient C# 5.0 / .NET 4.5 VB 2012
3 コレクション ArrayList/Hashtable → ジェネリックコレクション C# 2.0 / .NET 2.0 VB 2005
4 リソース管理 try/finally で Dispose → using/await using using (C# 2.0),await using (C# 8.0) using (VB 2005),await using (❌ 非対応)
5 LINQ 手続きループ処理 → LINQ(適材適所) LINQ (C# 3.0 / .NET 3.5) VB 2008
6 文字列処理 String.Format/連結 → 文字列補間($"") C# 6.0 / .NET 4.6 VB 2015
7 パターン is + キャスト → パターンマッチング C# 7.0 TypeOf…Isなどで可能だが ❌C# のような構文は非対応
8 制御フロー switch 文 → switch 式 C# 8.0 / .NET Core 3.0 ❌switch 式は非対応
9 DTO DTO クラス冗長 → record/with C# 9.0 / .NET 5 ❌ 非対応
10 日時処理 DateTime.Now 乱用 → DateTimeOffset.UtcNow .NET 2.0 ライブラリ側対応
11 シリアライザ BinaryFormatter/旧シリアライザ → System.Text.Json .NET Core 3.0 / .NET 5 ライブラリ側対応
12 スレッド管理 Thread 直使用 → Task/ThreadPool C# 4.0 / .NET 4.0 VB2010
13 タイマー Timer 多用 → PeriodicTimer (.NET 6+) .NET 6 ライブラリ側対応
14 データ層 ADO.NET 同期 API → 非同期/軽量 ORM C# 5.0 / .NET 4.5 VB2012
15 乱数生成 Random の単純使用 → RandomNumberGenerator .NET 5以降に推奨パターンとして定着 C# 同様
16 例外処理 例外の後処理 → 例外フィルタ catch when C# 6.0 / .NET 4.6 VB2015
17 Null チェック if (obj != null) だらけ → ?. / ??= / Nullable ?. (C# 6.0), ??=, Null許容参照型 (C# 8.0) ?. (VB2015),??=(❌ 非対応)
18 プロパティ 手書きプロパティ → 自動実装/式本体メンバー 自動実装 (C# 3.0), 式本体 (C# 6.0) 自動実装(VB2008),式本体(VB2015)
19 インスタンス化 new Type() 明示 → 目標型 new ターゲット型の new() (C# 9.0 / .NET 5) ❌ 非対応
20 データコピー 手動コピー → with/分解(ValueTuple) C# 7.0 / .NET 4.7 VB2017
21 設定管理 app.config/Web.config → appsettings.json + Options .NET Core 1.0 / .NET 5 ライブラリ側対応
22 ログ出力 Trace.WriteLine → ILogger .NET Core 1.0 / .NET 5 ライブラリ側対応

コレクション・データ型関連

4) try/finally で Dispose → using/await using

async の場合は await using

C# After
await using var fs = new FileStream(
    path, FileMode.Open, FileAccess.Read, 
    FileShare.Read, bufferSize: 4096, options: FileOptions.Asynchronous);

// .NET 6+ 推奨:Memory<byte> + CancellationToken
var buffer = new byte[1024];
int read = await fs.ReadAsync(buffer.AsMemory(), CancellationToken.None);

// または古いオーバーロード(.NET Framework との互換性が必要な場合)
int read2 = await fs.ReadAsync(buffer, 0, 1024);

VB.NET にはAwait Usingが存在しない
そのため、非同期解放が必要な場合はFinallyAwait DisposeAsync()を明示的に呼ぶ

VB After
Dim fs As FileStream = Nothing

Try
    fs = New FileStream(
        path, FileMode.Open, FileAccess.Read, FileShare.Read,bufferSize:=4096, options:=FileOptions.Asynchronous)

    ' .NET 6+ 推奨:Memory(Of Byte) + CancellationToken
    Dim buffer(1023) As Byte
    Dim read As Integer = Await fs.ReadAsync(buffer.AsMemory(), CancellationToken.None)

    ' または古いオーバーロード(.NET Framework 互換)
    Dim read2 As Integer = Await fs.ReadAsync(buffer, 0, 1024)

Finally
    ' await using が使えないため、明示的に非同期解放
    If fs IsNot Nothing Then
        Await fs.DisposeAsync()
    End If
End Try

LINQ・言語機能関連

7) is + キャスト → パターンマッチング

C# After
if (obj is Customer c)
{
    Console.WriteLine(c.Name);
}

補足: VB.NET もパターンマッチング(TypeOf ... Is ...)は可能ですが、C# のようにis Customer c同時に変数宣言する構文はありません。

VB After
If TypeOf obj Is Customer Then
    Dim c = CType(obj, Customer)
    Console.WriteLine(c.Name)
End If

8) switch 文 → switch 式

C# After
string msg = status switch 
{ 
    0 => "OK", 
    1 => "Warn", 
    _ => "NG" 
};

VB.NET は値を返す式としてのswitchはサポートされていません。
Select Caseは、break文が不要

VB After
Dim msg As String
Select Case status
    Case 0
        msg = "OK"
    Case 1
        msg = "Warn"
    Case Else
        msg = "NG"
End Select

このくらいなら、三項演算子で代用

VB After
Dim msg = If(status = 0, "OK", If(status = 1, "Warn", "NG")

DTO・オブジェクト関連

DTO クラス冗長 → record/with

C# After
public record User(string Name, int Age);

// 用途(同じ)
var user = new User("Alice", 30);

// with で不変コピー
var user2 = user with { Age = 31 };

VB.NET には C# のrecord型の等価機能がありません。
代替としては、ClassまたはStructureを使用し、必要な等価性・コピー機能を自前で実装します。
もしくは、VB-Record-Source-Generator を使う。
with式に対応していません

Null チェック・参照関連

17) if (obj != null) だらけ → ?. / ??= / Nullable Reference Types

C# After
name = user?.Name;  // user が null なら null を返す

config ??= DefaultConfig();  // null 時だけ代入

VB.NET にはC# の????=はありません。
三項演算子で書けるが、完全には同等ではない

VB After
name = user?.Name  ' user が Nothing なら Nothing を返す

' 三項演算子+一時変数でほぼ同等
Dim tmp = config
config = If(tmp = Nothing, DefaultConfig() : tmp)

C# 8.0 以降で??=が追加された理由は

  • 三項演算子では 安全・簡潔に書けない(ローカル変数限定 なら可)
  • 特にプロパティやフィールドで問題が起きやすい

インスタンス作成関連

19) new Type() 明示 → 目標型 new

After C#
List<string> list = new();
Dictionary<int, string> dict = new();

VB.NET ではC# のtarget-typed new省略は非対応

Before VB
Dim list As New List(Of String)
Dim dict As New Dictionary(Of Integer, String)()

オブジェクトコピー関連

20) 手動コピー → with/分解(ValueTuple)

ValueTuple で分解

After C#
var (min, max) = GetRange();

VB.NET では、タプルを複数の変数に“アンパック”する方法はない
変数ごとに1行が必要になる。

After VB
Dim r = GetRange()
Dim min = r.min
Dim max = r.max

VB.NET は with式に対応していません

最後に

VB.NETは、言語の進化(新機能の追加)を停止しました。Visual Basic 2017 が最後の新機能の追加となっています。
例として ??=recored型、パターンマッチング、直近だとfieldキーワード が対応していません。

ただし、ライブラリ側の新機能は、VB.NET でも対応しています。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?