オブジェクトのプロパティを読み取るとき、これまではオブジェクトの存在をチェックするコードを書いていただろう。例えば次のコードのように。
Dim name As String = Nothing
If (customer IsNot Nothing) Then
name = customer.Name
End If
VB 14で導入されたNull値反映演算子*3「?.」を使うと、上のようなNullチェックの記述が不要になるのだ(次のコード)。
Dim name As String = customer?.Name
' customerがNothingのときは、name変数にNothingが入る
「?.」演算子は、その直前の変数がNothingならばそこで評価を打ち切ってNothingを返すのである。Nothingでなければ、これまでの「.」と同じ動作をする。
*3 英語版のMSDNでは「Null-Propagating Operator」と呼ばれている。日本語訳は「Null値反映演算子」となるもようだ。
「Null」とは、C#などの言語にある機能で、VBのNothingとだいたい同じものである。しかし、VBだからといって「Nothing反映演算子」と呼んだりはしないようである。
VB 14では、改行を含む文字列リテラルを記述するときに、いちいち改行文字を連結しなくてもよくなった(次のコード)。C#では初期からあった機能だけに、ようやくVBにもきたかという感がある。
' 従来の記法:
Dim s1 = "1行目" & vbCrLf &
"2行目"
' VB 14の記法:
Dim s2 =
"1行目
2行目"
' 注意:次のように書くと、「2行目」の手前に空白が含まれてしまう
Dim s3 = "1行目
2行目"
変数名やプロパティ名などを文字列リテラルとして記述することはよくある。例外メッセージやイベント引数(例えばSystem.ComponentModel名前空間のPropertyChangedEventArgsクラス)などだ。
名前を文字列リテラルとして埋め込んでいると困るのが、名前を変更するときだ。リファクタリング機能で文字列の中も自動的に変更できるとはいえ、それには関係のない文字列の内容をうっかり変えてしまわないよう細心の注意が必要となる。
VB 14のNameOf演算子は、変数名やプロパティ名など、およそあらゆる名前が付いているものの名前を取り出してくれる(次のコード)。
' 従来の記法:
Public Sub NameOfSample01(arg1 As String)
If (arg1 Is Nothing) Then
Throw New ArgumentNullException("arg1", " NameOfSample01")
End If
End Sub
' VB 14の記法:
Public Sub NameOfSample01(arg1 As String)
If (arg1 Is Nothing) Then
Throw New ArgumentNullException(NameOf(arg1), NameOf(NameOfSample01))
End If
End Sub
' オブジェクトのプロパティ名の例
Public Sub NameOfSample02(cust As Customer)
If (cust.Name Is Nothing) Then
Throw New ArgumentNullException(NameOf(cust.Name))
' 「cust.Name」ではなく、「Name」になる
' 次のように書いても同じ
'Throw New ArgumentNullException(NameOf(Customer.Name))
End If
End Sub
なお、NameOf演算子はコンパイル時に解決される。プログラム的には文字列リテラルを記述したのと同じであり、実行速度に違いは出ない。また、コンパイル時に決定できない名前(例えばリフレクションで取得したオブジェクトの名前など)は使用できない。
文字列の書式をStringクラス(System名前空間)のFormatメソッドを使って整えるときに、変数の順序を間違えてしまったことはないだろうか? VB 14の「文字列補間*4」は、そんなミスを防いでくれる(次のコード)。
Dim unitPrice = 700
Dim count = 3
Dim tax = Math.Floor(unitPrice * count * 8.0 / 108.0)
' 従来の記法:
Dim msg1 = String.Format("単価{0:#,#}×{1}個={2:#,#}円 (内消費税{3:#,#}円)",
unitPrice, count, unitPrice * count, tax)
' VB 14の記法:
Dim msg2 = $"単価{unitPrice:#,#}×{count}個" &
$"={unitPrice * count:#,#}円 (内消費税{tax:#,#}円)"
' msg1/msg2とも、次の結果になる
' "単価700×3個=2,100円 (内消費税155円)"
文字列内のプレースホルダーに変数や式を記述できるので、これまでのようにプレースホルダーの番号と与える変数の並び順の関係に気を使わなくてよいのである。
*4 英語版のMSDNでは「String Interpolation」と呼ばれている。日本語訳は「文字列補間」となるようだ。ちなみに、「interpolation」を「補間」と訳すのは数学用語の場合である(「関数の補間」など)。「interpolation」の一般的な意味は「加筆」「挿入」など、既存の文書に文字を書き加えることである。なお、「補完」であれば、足りないところを補って完全にするという意味だ(ただし、「interpolation」とは意味が変わってしまう)。
これは今までできなかったのが不思議なくらいの機能である。複数行にわたる文の途中でも、VB 14では行末にコメントが書けるようになったのだ(次のコード)。ただし、行連結シーケンス(空白とそれに続くアンダースコア「_」)を使わずに、暗黙の行連結を行っている場合だけである。
Dim unitPriceWithoutTax = 100
Dim count = 3
Dim taxRate = 0.08
Dim totalWithTax As Integer = ' 消費税を含む合計金額は
unitPriceWithoutTax * ' 消費税別の単価に
count * ' 個数を掛けて
(1 + taxRate) ' さらに(1+消費税率)を掛けたもの
' 以下のような行連結シーケンスを使った書き方はコンパイルエラーになる
'Dim totalWithTax1 As Integer _ ' 消費税を含む合計金額は
' = unitPriceWithoutTax _ ' 消費税別の単価に
' * count _ ' 個数を掛けて
' * (1 + taxRate) ' さらに(100%+消費税率)を掛けたもの
VB 14の新機能、いかがだろうか。しかし本稿で紹介できたのは、ほんの一部分にすぎない。
これまでのVBは、リファクタリングのサポート機能が備わっていなかったり、共有プロジェクトが提供されなかったり、言語の新機能もC#から1〜2バージョン遅れて提供されたりしてきた。「VBだから周回遅れでもしょうがないよね」などといわれたりもしたものだ。
冒頭にも述べたように、VB 14は全面的に書き直された。それによって、ここで紹介したようなさまざまな新機能が搭載され、一挙にC#に追いついたといってよいだろう。もう「VBだから」とは言わせない!
Copyright© Digital Advantage Corp. All Rights Reserved.