特集
PDC05レポート

動的プログラミング言語へと発展するC# 3.0とVB 9.0

吉松 史彰
2005/10/13

Page1 Page2 Page3 Page4

Visual Basicを再び動的プログラミング言語にする試み

 本レポートの最後に触れておきたいのが、動的型付言語としてのVB9固有の拡張機能である。

 VBにはC#にはない大きな特徴がある。遅延バインディング(Late Binding)支援機能だ。C#ではリフレクション構文を使って書かなければならないコードを、VBではあたかも型の内容を知っているかのように書くことができる。これはCOM Interop(COM相互運用)でExcelのセルを操作するようなコードを書くときなどに重宝する。

 だが一方で、Option Strict Onを無条件に推奨するような風潮の中では、VBのこの機能はVBが「本物のプログラミング言語」になるためには捨て去るべき過去の遺物のように扱われているのも事実だ。

 結局のところ、.NET Frameworkにおける当初のメッセージは「どの言語でも同じ」だったのだから、C#とVBに違いがあってはならず、VBはC#の後を追いかけているような印象を常に与えていた。

 しかし今回のPDC05では、VBチームはいよいよこの風潮と決別しようとしていることが明らかになった。「My」の導入やフォームをインスタンス化する構文など、OOP(オブジェクト指向プログラミング)至上主義からは反対される機能をVisual Basic 2005で導入したことは前触れにすぎなかった。

 PDC05で発表されたVB9は、もともと動的型付言語だった時代のVBからの、いまはやりの動的型付言語に対する回答だ。

■遅延バインディングによるXMLアクセス

 VBで遅延バインディングを有効にしていると、次のようなコードがコンパイルできる(この場合は実行時例外となる)。

Option Strict Off
Imports System

Class Person
  Friend Name As String
End Class

Module Module1
  Sub Main()
    Dim p As New Person()
    p.Name = "Yoshimatsu"
    ProcessPerson(p)
  End Sub

  Sub ProcessPerson(p As Object)
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName)
  End Sub
End Module

 静的型付言語の発想からするとこのようなコードは許されるものではない。

 しかし、XML文書にアクセスするときには次のコードのように文字列でタグ名を記述しなければならず、結果として遅延バインディングを行っていることになる。

' VB9
For Each link As XElement In Select links From links In (Select item.Descendants("link") From item In rss.Descendants("item"))
  Console.WriteLine(link.Value)
Next

 どうせ文字列で識別子を指定して暗黙に遅延バインディングをしなければならないのだとしたら、このような不自然な記述をプログラマに強いる必要がどこにあるだろうか。VB9ではこのコードは次のように書いてコンパイルできる。

' VB9
For Each link In rss...item...link
  Console.WriteLine(link.Value)
Next

 属性には「rss...item...enclosure.@type」のような書き方でアクセスできる。コンパイル時点では、読み込まれたXML文書にitem要素が含まれるかどうかはいずれにしても分からないのだから、遅延バインディングをせざるを得ない。それならせめてコードは簡単に書けた方がいい。

■Extreme Late Binding

 JavaScriptでは、次のようなコードを記述できる。

class1 = function() {
  var _name = "Yoshimatsu";
  var _age = 22;
  this.get_Name = function() { return _name; }
  this.get_Age = function() { return _age; }
}

function callMethod(obj, methodName) {
  return obj[methodName]();
}

function main() {
  var obj = new class1();
  WScript.Echo(callMethod(obj, "get_Name"));
  WScript.Echo(callMethod(obj, "get_Age"));
}

main();

 このコードを実行すると、「Yoshimatsu」と「22」が表示される。つまり、オブジェクトに対してメソッドを呼び出すのだが、呼び出すメソッドの名前は実行してみないと分からないのである。これも遅延バインディングの例だ。従来のVBでも、リフレクションのコードを記述すればこのような動作は可能だったが、リフレクションのコードを書くのはとにかく面倒だ。

 VB9では次のコードを実行できる。「p.(propName)」のようにメソッド呼び出しにカッコを付けていることに注意してほしい。

Option Strict Off
Imports System

Class Person
  Private _Name As String = "Yoshimatsu"
  Private _Age As Integer = 22

  Public ReadOnly Property Name As String
    Get
      Return _Name
    End Get
  End Property

  Public Readonly Property Age As String
    Get
      Return _Age
    End Get
  End Property
End Class

Module Module1
  Sub Main(Args As String())
    Dim p As New Person()
    ProcessPerson(p, Args(0))
  End Sub

  Sub ProcessPerson(p As Object, propName As String)
    Console.WriteLine(p.(propName))
  End Sub
End Module

■“Strong Duck Typing” ? − Dynamic Interface

 「アヒルのように歩き、アヒルのように鳴くものは、アヒルに違いない」

 静的型付言語では次のコードはコンパイルできない。

Option Strict On
Imports System

Class Person
  Public Name As String
End Class

Class PetAnimal
  Public Name As String
End Class

Module Module1
  Sub Main()
    Dim p As New Person()
    p.Name = "John"
    Dim q As New PetAnimal()
    q.Name = "Pochi"
    ProcessFamily(p)
    ProcessFamily(q)
  End Sub

  Sub ProcessFamily(p As Object)
    Console.WriteLine(p.Name)
  End Sub
End Module

 PersonクラスにもPetAnimalクラスにもNameフィールドがあるにもかかわらず、このコードはコンパイルできない。このコードをコンパイルするには、Option Strict Offにして、コンパイラの助けを一切あきらめ、その後あらゆるコードについて正しくタイピングしたことを自分で保証する以外にない。

 VB9では、「Dynamic Interface」の機能により次のようなコードがコンパイルできるようになる予定だ。残念ながらPDC05後に配布されたプレビュー版コンパイラにもこの実装は含まれていない。

Option Strict On
Imports System

<Dynamic> _
Interface IHasName
  ReadOnly Property Name As String
End Interface

Class Person
  Private _Name As String
  Public ReadOnly Property Name As String
    Get
      Return _Name
    End Get
  End Property
End Class

Class PetAnimal
  Private _Name As String
  Public ReadOnly Property Name As String
    Get
      Return _Name
    End Get
  End Property
End Class

Module Module1
  Sub Main(Args As String())
    Dim p As New Person()
    Dim q As New PetAnimal()
    ProcessFamily(p)
    ProcessFamily(q)
  End Sub

  Sub ProcessFamily(p As IHasName)
    Console.WriteLine(p.Name)
  End Sub
End Module

 IHasNameインターフェイスは通常のInterface型ではなく、<Dynamic>属性によりVB9コンパイラに対するヒントとして機能する。コンパイル後はProcessFamilyメソッドが取るパラメータはObject型になる。だが、「As Object」とすると失われてしまうIntelliSense機能やコンパイル時の型チェックはDynamic Interfaceによって維持される。

 これらの機能はいずれも最近の動的型付言語に何らかの形で含まれている。VBはそのルーツであるBASICの動的型付言語としての側面を排除し続けてこれまで進化してきた。しかしVB9は再度遅延バインディングを主要機能として前面に押し出し、特徴ある言語としての生き方を模索しようとしているようだ。

 なお、ここまでの解説で「オブジェクト指向」という言葉をほとんど使わなかったことに気付いてほしい。動的な型付きとオブジェクト指向は両立する。Interface型によるポリモーフィズムだけがOOPではない。動的なプログラミングへの流れは、必ずしもオブジェクト指向と矛盾するものではない。

まとめ

 PDC05で紹介されたMicrosoftの取り組みは、必ずしも技術として目新しいものではない。実際、本レポートで紹介したRSS、Ajax、動的プログラミングはいずれもすでに実践されているもので、Microsoftが発明したものではない。その意味では、今回のPDCはそれほどエキサイティングな場ではなかったのかもしれず、前編の冒頭で触れたPDCの法則は当たってしまったのかもしれない。

 しかし、Microsoftはいつも追いかける立場にあってこそ技術を進歩させてきた。Javaを追いかけてCLRを作り、Netscapeを追いかけてInternet Explorerを作った。PDC05が先行者を追いかけ始める“のろし”だったのかどうか、答えはそう遠くない将来に出ることだろう。End of Article

 

 INDEX
  [特集] PDC05レポート
  巻き返しが始まるMicrosoftのRSS/Ajax戦略
    1.PDC05の3つのテーマ
    2.RSSへの取り組み
    3.Ajaxと新世代Webアプリケーション
  動的プログラミング言語へと発展するC# 3.0とVB 9.0
    1.動的型付言語への憧憬
    2.型推論とラムダ式/Extension Methodsの導入
    3.クエリ構文の統合「LINQ」/DLinqとXLinq
  4.Visual Basicを再び動的プログラミング言語にする試み
 


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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間