特集:VB 10概説

Visual Basic 2010の新機能

尾崎 義尚
2011/05/17
Page1 Page2 Page3 Page4

3. C#から引き継がれた新機能

 前述のとおり、VB 2010からはC#と機能が統一されることになったため、前のバージョンであるC# 3.0(=C# 2008)で実装されていた機能がVB 2010で追加されている。ここではC# 2008で実装されていて、今回VB 2010に追加された機能について解説する。

自動実装プロパティ

 自動実装プロパティは、C# 2008で実装されていた機能の中で最もうれしかった機能の1つであり、VB 2008に実装されていないことを知ったとき、非常に残念に思ったことを覚えている。

 これまで、プロパティを実装するためには、フィールド変数とGet/Setプロシージャが必要だった。これを書くのが面倒で、Publicのフィールド変数を宣言して代用することがままあった。

 以下がVB 2008までのプロパティ実装の例である。

Private _name As String
Public Property Name() As String
  Get
    Return _name
  End Get
  Set(ByVal value As String)
    _name = value
  End Set
End Property
VB 2008までのプロパティ実装の例
Private変数の宣言とGet/Setプロシージャの記述が必要だった。

 VB 2010では、以下のように非常にシンプルに記述することができる。

Public Property Name As String
VB 2010の自動実装プロパティの例
Private変数、Get/Setプロシージャの記述が不要になり、フィールド変数の記述に近くなった。

 この記述はC#よりもシンプルで、Propertyというキーワードがある以外はフィールドを宣言するのとまったく変わらない。C#では、get/setアクセサの記述が必要である。参考までにC#の自動実装プロパティを記載する。

public string Name
{
  get;
  set;
}
C#の自動実装プロパティの例
C#では、変数の宣言は不要になっているが、get/setアクセサの記述は必要である。

 運よく、VBには、Propertyというキーワードがあったため、C#のようにアクセサを記述しなくてもプロパティであることが識別できるようになっている。このときVBコンパイラは、「_Name」というアンダーバー+プロパティ名のPrivate変数に展開する。そのため、「_Name」という名前のフィールド変数を宣言すると、コンパイル時に以下のような「競合エラー」が発生する。

error BC31061: 変数 '_Name' は、class 'c1' にある property 'Name' に対して暗黙的に定義されたメンバーと競合しています。
  Private _Name as String
アンダーバー+プロパティ名と同名のフィールド変数がある場合のコンパイル・エラー
自動実装プロパティは、「_」(アンダーバー)+プロパティ名という変数に展開されるため、同じ名前のフィールド変数が宣言されているとコンパイル・エラーになる。

 ご存じのとおり、VBは大文字、小文字を区別しないため、「_name」のように小文字にしても同様に競合エラーになる。

コレクション初期化子

 値があらかじめ決まっているときには、定数を使用するか、変数を初期化するときに値を初期化することができる。しかし、コレクションではこれを行うことができなかった。あらかじめコレクションの値が固定されている場合、コレクションにすべてのアイテムを追加するまでが変数を初期化することであるが、VB 2008までは初期化するために複数行の記述が必要であった。

 以下にVB 2008でのコレクションを初期化しているサンプルを記述する。

Dim statuses As New Dictionary(Of Integer, String)

statuses.Add(1, "申請")
statuses.Add(2, "課長承認")
statuses.Add(3, "部長承認")
statuses.Add(50, "承認済み")
statuses.Add(80, "差し戻し")
statuses.Add(99, "却下")
VB 2008のコレクションの初期化
VB 2008では、コレクションを初期化するために、メソッドを呼び出す必要があった。

 このようにVB 2008では、コレクションの初期化のために複数行の記述が必要であった。VB 2010では以下のように、コレクションのインスタンス化のときに初期値を設定できるようになっている。

Dim statuses As New Dictionary(Of Integer, String) From
{
  {1, "申請"},
  {2, "課長承認"},
  {3, "部長承認"},
  {50, "承認済み"},
  {80, "差し戻し"},
  {99, "却下"}
}
VB 2010のコレクションの初期化
Fromキーワードの後ろに初期値を記述することで、コレクションをインスタンス化すると同時に初期化できるようになった。

 このようにVB 2010では、Fromキーワードを使用することで、コレクション変数のインスタンス化と同時にアイテムの追加が行えるようになっているため、初期化処理が複数行にまたがることがなく、分かりやすい記述ができるようになっている。From句は、LINQでも使用されているコレクションを指定するためのキーワードで、同じくコレクションを記述するために採用されている。

 また、プロパティ名を指定して初期化する時は、With句を使用するようになっている。次のコードはその例である。

' クラスの宣言
Public Class OS
  Public Property Version As Single
  Public Property Name As String
End Class

……省略……

' 変数の宣言と初期化
Dim oses As New List(Of OS) From
{
  New OS With {.Name = "Windows XP", .Version = 5.1},
  New OS With {.Name = "Windows Vista", .Version = 6},
  New OS With {.Name = "Windows 7", .Version = 6.1}
}
プロパティ名を指定して初期化
プロパティ名を指定して初期化する場合、From句に加えて、クラスをインスタンス化するNew句とWith句を使用する。

 初期化の実装をよりすっきりさせるために、拡張メソッドを使用した方法を紹介しよう。なお拡張メソッドは、VB 2008で追加された機能のため、本稿では解説を省略するが、詳細を知りたい場合は、「VB開発者のための拡張メソッド入門」を参照してほしい。

 コレクションの初期化では、Addメソッドが呼び出されるため、Addメソッドをオーバーロードすればよいのだが、ジェネリックのListクラス(System.Collections.Generic名前空間)の場合、継承したクラスを作成するか、拡張メソッドで実装する方法がある。拡張メソッドを実装する場合は、下記のようなコードを書く。

' List(Of OS)クラスに対する拡張メソッドを実装
<Extension()> Public Sub Add(ByVal items As List(Of OS), ByVal version As Single, ByVal name As String)
  items.Add(New OS With {.Version = version, .Name = name})
End Sub

……省略……

' 変数の宣言と初期化
Dim oses As New List(Of OS) From
{
  {5.1, "Windows XP"},
  {6.0, "Windows Vista"},
  {6.1, "Windows 7"}
}
拡張メソッドを使用してAddメソッドを実装した例
拡張メソッドでAddを実装して、拡張メソッドの中で初期化を行うことで、呼び出し側の実装を簡略化している。

 このように、拡張メソッドを使用してAddメソッドをオーバーロードすることにより、初期化処理をシンプルに記述できるようになる。なお、異なる順序での初期化が必要な場合、それぞれの順序での拡張メソッドが必要になる。

 ただし、オブジェクト初期化子とコレクション初期化子は同時に使えないため、オブジェクトの初期化が必要な場合は、初期化の後でコレクションの初期化を行う必要がある。下記のコードはその例だ。

Dim numbers As New List(Of Integer) With {.Capacity = 5}
' From
' {
'   1, 2, 3, 4, 5
' }
numbers.Add(1)
numbers.Add(2)
numbers.Add(3)
numbers.Add(4)
numbers.Add(5)
オブジェクト初期化子とコレクション初期化子を組み合わせることはできない
このように、オブジェクトの初期化が必要な場合は、オブジェクト初期化子で初期化した後で、コレクションのアイテムを追加していく必要がある。

複数行のラムダ式

 VB 2008では、ラムダ式が1行しか書けなかったので、複雑な処理をラムダ式で記述できなかった。そのため、再利用性がないコードでも、メソッドとして切り出して呼び出す必要があった。

 VB 2010では、以下のように複数行のコードを記述することが可能になっている。

Dim r = 20.0
Dim pi = Function(birthday As Date)
           If birthday.Year > 1990 AndAlso
             birthday.Year < 2000 Then
             Return 3
           Else
             Return 3.14
           End If
         End Function
Console.WriteLine(pi(Date.Today) * r * r)
VB 2010のラムダ式の例
VB 2010では、複数行のラムダ式を記述できるようになっている。

 このように「Function」(または「Sub」)でメソッドを記述するのと同じようにラムダ式を記述して、呼び出せるようになっている。

 続いて、.NET 4からの新機能について解説する。


 INDEX
  特集:VB 10概説
  Visual Basic 2010の新機能
    1.「_」(アンダースコア)が不要になった=「暗黙の行継続」
  2.C#から引き継がれた新機能:自動実装プロパティ/コレクション初期化子/複数行のラムダ式
    3.VB 2010の新機能:ジェネリックの共変性と反変性/動的プログラミングのサポート
    4.VB 2010の新機能:並列処理、 Visual Studio 2010 SP1の新機能


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH