こんにちは!開発現場の最前線で、日々コードの品質と格闘している先輩エンジニアです。
今回は、Visual Basic(VB.NET)における「文字列から数値への変換」という、誰もが最初に直面し、そしてベテランになっても時々足をすくわれる罠についてお話しします。
「画面のテキストボックスに入力された値を計算に使いたいだけなのに、なぜかエラーで落ちる……」
「古いコードを直していたら、`Val`関数や`CInt`関数が使われていて、なんだかきな臭い……」
そんなモヤモヤを抱えているあなたへ。ここをクリアすれば、VB.NETの数値処理の基本はバッチリですよ。レガシーな変換関数の危険性を紐解きながら、現代のモダンな開発で必須となる安全なアプローチまで、一緒にしっかりとマスターしていきましょう!
—
1. 3大・数値変換「Val」「CInt」「CLng」の正体と危険な挙動
まずは、VBの歴史的背景とともに受け継がれてきた、おなじみの変換関数たちを見てみましょう。これらは手軽な反面、「意図しない挙動やクラッシュ」の爆弾を抱えています。
① `Val` 関数:実は「なんでも屋」だけど超ルーズ
`Val`関数は、文字列の先頭から数値を読み取り、数値に変換できるところまでを抽出するレガシーな関数です(VB6以前から存在します)。
Dim result As Double = Val(“1234円”) ‘ 結果は 1234
Dim result2 As Double = Val(“A123”) ‘ 結果は 0 (文字から始まると諦める)
【ここが危険!】
- エラーを一切出さず、勝手に解釈して `0` や途中の数値にしてしまいます。
- 金額や数量の入力チェックに使うと、ユーザーが入力した誤った文字をサイレントに無視して処理が進んでしまうため、バグの温床になります。
- 戻値が `Double` 型なので、整数として扱いたい場合にも注意が必要です。
② `CInt` / `CLng` 関数:厳格だが「一発レッドカード」
`CInt`(Integer型へ変換)や `CLng`(Long型へ変換)は、 .NETの世界の型変換(DirectCast等)のラッパーとして機能する強力な関数です。
Dim num As Integer = CInt(“12345”) ‘ 正しく 12345 に変換される
【ここが危険!】
- もし文字列が `”ABC”` のような数値にできないものだったら? $\rightarrow$ 容赦なく `InvalidCastException`(型不一致エラー)が発生し、アプリがクラッシュします。
- 値が大きすぎて Integer の範囲(約21億)を超えていたら? $\rightarrow$ `OverflowException`(オーバーフロー)が発生し、これまたアプリが強制終了します。
「じゃあ、エラーが出ないように事前にチェックすればいいんだな?」その通り!しかし、その「チェックと変換」をスマートかつ安全に行うのが、現代の .NET における鉄則なのです。
—
2. 図解:レガシー変換 vs モダンTryParse
古いアプローチとモダンなアプローチの違いを、処理の流れで比較してみましょう。
レガシーなアプローチ(例外頼み、またはノーチェック)
[入力値] ──> 【 CInt() 実行 】
├─ 成功 ──> [処理続行]
└─ 失敗 ──> 💥 【即時クラッシュ (例外発生)】
エラーが起きてから対処する(あるいは無視する)スタイルは、システムの本番環境において非常にリスキーです。
モダンなアプローチ(TryParseによる事前検証)
[入力値] ──> 【 Integer.TryParse() 】
├─ 成功 (True) ──> [安全に数値取得 & 処理続行]
└─ 失敗 (False) ──> [優しいエラーメッセージ表示]
「変換できるかどうかを事前に安全にテストし、ダメなら優しくハンドリングする」。これがプロフェッショナルのコードです。
—
3. 実践! `Integer.TryParse` で堅牢なコードを書く
それでは、現場で即戦力となるモダンな書き方を見てみましょう。VB.NETでは、各数値型(`Integer`, `Long`, `Decimal` など)に `TryParse` というメソッドが用意されています。
以下のコードは、コンソールやボタンクリック時を想定した実用的なスニペットです。
Imports System
Module NumericConversionSample
Sub Main()
‘ テスト用の入力値(わざと不備のある文字列を入れています)
Dim userInput As String = “123456”
‘ 変換後の値を格納する変数をあらかじめ用意しておく
Dim parsedValue As Integer = 0
‘ Integer.TryParse の使い方
‘ 第一引数: 変換したい文字列
‘ 第二引数 (ByRef): 成功した場合に数値が格納される変数
If Integer.TryParse(userInput, parsedValue) = True Then
‘ — 変換成功時の処理 —
Console.WriteLine(“変換に成功しました!”)
‘ すでに parsedValue には安全な Integer 型の値が入っている
Dim finalResult As Integer = parsedValue 2
Console.WriteLine($”計算結果: {finalResult}”)
Else
‘ — 変換失敗時の処理(クラッシュしない!) —
Console.WriteLine(“エラー: 有効な整数を入力してください。”)
‘ ここでユーザーに再入力を促すなどのリカバリ処理を書く
End If
End Sub
End Module
このコードの優れたポイント
1. 例外を投げない(パフォーマンスが高い):
`CInt` でエラーをキャッチしようとすると、例外オブジェクトの生成コストがかかりますが、`TryParse` は真偽値(Boolean)を返すだけなので非常に軽量です。
2. `ByRef` による値の受け渡し:
第二引数に `Out` パラメータ(VB.NETでは `ByRef`)として変数を渡すことで、成功時には自動的に値がバインドされます。
3. コードの意図が明確:
「この文字列は数値に変換できるか?」という条件分岐が一目でわかります。
—
4. さらに大きな数字を扱うときは? (`CLng` から `Long.TryParse` へ)
インベントリの数量や金額計算などで、Integerの範囲(約21億)を超える可能性がある場合は、`Long` 型(`Int64`)を使用します。もちろん、ここでも `TryParse` が大活躍します。
Dim inputAmount As String = “9876543210” ‘ 21億を超える大きな数字
Dim safeAmount As Long = 0
‘ Long.TryParse を使うことで、桁あふれ(オーバーフロー)もスマートに回避
If Long.TryParse(inputAmount, safeAmount) Then
Console.WriteLine($”安全に大きな数値を処理できました: {safeAmount}”)
Else
Console.WriteLine(“数値としての有効範囲を超えているか、文字が含まれています。”)
End If
—
まとめ:今日からあなたのコードを「モダン」にアップデートしよう
今回は、VB.NETにおける数値変換の裏側と、安全な `TryParse` への移行について解説しました。
- `Val` はルーズすぎるため、入力検証には絶対に使わない。
- `CInt` / `CLng` は、例外でアプリが落ちるリスクがあるため、中身が確実に数値だと保証されている場面以外では避ける。
- ユーザーからの入力や外部データには、必ず `Integer.TryParse` や `Long.TryParse` を使って安全性を担保する。
この基本を徹底するだけで、あなたの書くVB.NETコードの堅牢性は劇的に跳ね上がります。「動けばいいや」のコードから卒業し、メンテナンスしやすく信頼性の高いシステムを作っていきましょう。
あなたのエンジニアライフを、これからも応援しています!
