特集

PDC05レポート

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

吉松 史彰
2005/10/13
Page1 Page2 Page3 Page4

 VBプログラマは、ここ数年.NET Frameworkへの移行で四苦八苦してきた。

 「静的型付言語」であるVisual Basic .NET(VB.NET)で従来のVBプログラマがまず叩き込まれるのは、「Option Strict On」である。これによって、Visual Basicコンパイラが「正しい行い」をプログラマに強制する。VBプログラマの苦痛は、VBが中途半端なニセモノプログラミング言語の汚名から解放され、真のプログラマが利用する言語へと進化するための痛みとして認識されている。

 .NET Framework 2.0でジェネリックが導入されることになったとき、多くの紹介記事でいわれたことは「これでコレクションに伴う実行時例外の危険が排除され、また1つ静的型付言語が完ぺきに近づいた」ということだった。静的型付言語を利用したプログラムでは、エラーはコンパイル時に捕捉されるもので、実行時例外とは文字どおり本物の例外的事象であり、あってはならないものと考えられている。

 PDC05に先立つこと2カ月、MicrosoftのErik Meijer、Peter Drayton両氏は連名で示唆に富んだ文書を発表した。「Static Typing Where Possible, Dynamic Typing When Needed: The End of the Cold War Between Programming Languages(PDF)」と題したこの文書の中で両氏は、「静的型付言語と動的型付言語のそれぞれよいところを取った中間的なものを指向したい」と書いている。

 静的な型付きでは、コンパイラによるプログラムミスの早期発見と最適化、型の明示に伴うドキュメントの充実などが利点として挙げられることが多い。いまやVBプログラマですら静的な型付きのプログラミングをしなければ「正しいプログラム」と認めてもらえないほど、静的型付プログラミングは浸透してきている。Javaが流行したのもその一因であることは間違いない。

 しかし、VBプログラマの苦痛とは裏腹に、世界は静的型付言語の夢から覚めようとしている。

 Perl、Ruby、Python、JavaScriptなどの多様な言語が、主にWindows以外のプラットフォームで大規模アプリケーションを稼働させるようになり、シリコンバレーでプログラマの職を得ようと思ったら、JavaやC#ではなくこれらの言語を知らなければならない。.NET構想が過去の遺物として捨て去ろうとしてきた動的型付言語が、いま大きな注目を集めているのである。

コンパイラは全能か?

 「Option Strict On」では、次のVB.NETコードはコンパイル・エラーになる。

Imports System
Module Module1
  Sub Main()
    Dim x = "&H1"
    Dim y = "2"
    Dim z = Add(x, y)
    Console.WriteLine(z)
  End Sub

  Function Add(ByVal x, ByVal y)
    Return x + y
  End Function
End Module

 「Option Strict Off」ではこれがコンパイルでき、実行結果として「&H12」と表示されるのを見れば、さらには「Dim y = 2」としてyを文字列ではなく数値で初期化して実行すると実行結果として「3」と表示されるのを見れば、Option Strict Onの恩恵も分かろうというものだ。哀れな子羊がコンパイラのお助けを請うためのオマジナイというわけだ。

 だが、静的型付きの環境で書いたコードのすべてに静的な型が付いているわけではない。なるほどArrayListクラスやHashtableクラスなどのコレクションではジェネリックが導入され、静的な型付きのコレクションが利用できるようになった。

 しかしADO.NETではどうだろうか。.NETリモート処理(.NET Remoting)ではどうだろうか。XPathではどうだろうか。次のコードで、変数IDに数値が入ることはコンパイラによって保証されるだろうか。

Option Strict On
Imports System
Imports System.Data.SqlClient
Module Module1
  Sub Main()
    Dim cn As New SqlConnection("Integrated Security=SSPI;Initial Catalog=SomeData")
    Dim cmd As New SqlCommand("SELECT ID From Employees", cn)
    Dim r As SqlDataReader = cmd.ExecuteReader()
    Do While (r.Read())
      Dim ID As Integer = CInt(r.GetValue(0))
      ' ……
    Loop
  End Sub
End Module

 もちろん保証されない。にもかかわらずこのコードはコンパイルされる。プログラマは何らかの手段であらかじめIDデータが数値であることを知っており、その暗黙の知識をコードに埋め込んでいる。実際、そのデータが数値に変換できない場合には、このコードは実行時例外を起こす。

 同様のことは、XML文書を扱うAPIにもいえる。XPath式や要素のタグ名を記述するとき、コンパイラはそれが正しいツリー構造に基づいた表現かどうかをチェックしない。

 一方、静的型付言語では、不要なまでに静的な型が強制されることもある。次のコードがコンパイルできないとしたら、コンパイラは意地悪をしているとしか思えないだろう。

Dim x As Nullable(Of Integer) = 1
Dim y As Nullable(Of Integer) = 2
Dim z As Nullable(Of Integer) = x + y

 実際には次のように記述しなければならない。

Dim z As Nullable(Of Integer) = x.GetValueOrDefault + y.GetValueOrDefault

 C#コンパイラがVB.NETよりも賢いというなら(上のコードはC#ではコンパイルできる)、なぜC#では以下のように記述しなければならないのか? どうして何度も型名を記述しなければならないのか?

// sがStringBuilderであるのは分かりきっているのに……
StringBuilder s = new StringBuilder();

// VBなら次のコードで書けるのに……
// Dim s As New StringBuilder()

動的型付言語への憧憬

 データベースやXML文書など、オブジェクト指向におけるオブジェクトやクラスではないものへアクセスするプログラムを当たり前のように書かなくてはならない現在では、上に挙げたような問題はプログラミングとは異なる領域での研究の対象になっている。例えばO/Rマッピング・ツールなどを別途用意し、システム開発時の設計を重視して後戻りをなくし、あるいは設計と実装を近づけ、設計の変化を柔軟に実装に取り込める方法論を確立するなどである。

 だが、プログラミング言語とコンパイラにできることはまだある。実際、多くの動的型付言語ではできていることなのに、静的型付言語ではなぜかできていないことは多い。C#とVBの次(Visual Studio 2005の次)のバージョン(これらは現在「C# 3.0」、「Visual Basic 9.0」という名前で呼ばれている。以下では「C#3」「VB9」と表記)では、まだあるいくつかの問題の解決に挑戦することが、C#とVBの担当者によって宣言された。

  • 暗黙の型指定
  • 型推論とラムダ式
  • Extension Methodsの導入
  • クエリの統合「LINQ」

 これらの機能は共通言語ランタイム(CLR)やフレームワーク・クラス・ライブラリのレベルではなく、できるだけ言語仕様とコンパイラのレベルで解決することが発表された。つまり、まもなく登場する共通言語ランタイムの新版(.NET Framework 2.0)の上で動作するということである。RubyやJavaScriptにすでに存在する機能が、C#やVBにも遅ればせながら提供されることになった。

■ローカル変数への暗黙の型指定

 例えばC#では当初のバージョンから、暗黙に型が指定されたオブジェクトがあった。例えば、リテラルで記述した「1」「1.0」「"1"」は、それぞれInt32型(int型)、Double型、String型として処理される。そのため、次のコードを実行すると結果は「0」となる。

class App {
  static void Main() {
    int x = 1;
    System.Console.WriteLine(x / 3);
  }
}

 にもかかわらず、C#では単純に「x = 1」などと書いて、変数xの型を暗黙的にint型にすることはできない。

 次のバージョンのC#3とVB9では、暗黙に型を指定できるようになった。これらは次のように記述すればよく、自明のことをわざわざ明示する必要はなくなる。

// C#3
var x = 1;       // xはint型
var s = "hello"; // sはstring型

' VB9
Dim x = 1       ' xはInteger型
Dim s = "hello" ' sはString型

 C#3ではオブジェクトを変数に代入するときなども型を明示しなくてもよくなる。

// C#3
var x = new StringBuilder();

' VB9
'Dim x As New StringBuilder(); ' すでに可能
Dim x = New StringBuilder()    ' VB9で可能


 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を再び動的プログラミング言語にする試み
 
更新履歴
【2005/10/20】本ページ内において以下の部分に誤りがありました。VB.NETでは型文字が指定されていない場合、Integer型の範囲内の値はInteger型となります。また、Integer型同士の「/」による除算はDecimal型に変換されて計算されます。お詫びして削除させていただきます。

削除

 一方VBでは、次のコードの結果は「0.333333333333333」になる。VBではリテラルの数値はDouble型になっている。

Module Module1
  Sub Main()
    Dim x As Integer = 1
    System.Console.WriteLine(x / 3)
  End Sub
End Module

にもかかわらず、VBで「Dim x = 1」と書いて変数xをDouble型にすることはできない。



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 記事ランキング

本日 月間