matarillo.com

The best days are ahead of us.

C#に関するアンダース ヘルスバーグへのインタビュー (2005年)

2012-07-17 19:45:12

翻訳許可を与えてくださったJohn Osborn氏とO’Reilly社に感謝します。

原文は下のリンクを参照してください。

C#: 昨日、今日、明日

アンダース・ヘルスバーグは1996年にマイクロソフトに転職し、初期はVisual J++とWindows Foundation Class (WFC) のアーキテクトとして仕事をした。 ヘルスバーグは現在Microsoft Distinguished EngineerかつC#のチーフアーキテクトであり、Microsoft .NET Frameworkを生み出すのに鍵となる役割を果たした。 今日では進行中であるC#の発展を指揮している。

ジョン・オズボーンはO’Reilly社の重役編集者であり、.NETやその他のMicrosoft主導技術に関する開発者向け書籍の責任者である。 ヘルスバーグと共にこの広範なインタビューを企画した。

目次

はじめに

Osborn:

前回話し合った2000年までさかのぼるべきかな。あのインタビュー面白かったよ。あの時はJavaにこだわってて、C#とJavaの比較をしたんだ。

Hejlsberg:

だね。

Osborn:

5年間という観点で……あの時を振り返り、そして今C#がいる場所を見れば……この言語はどこにいると思う?Microsoft専用ツールなのかな?コミュニティで広い場所を占めている何かなのかな?

Hejlsberg:

そうだね。5年のあいだにいろいろあった。世界はとても変わったように見える。……比べてみればわかる。ぼくらは.NETを持っていなかったし、Javaはもっと新しくて流行りだった。だからこそたくさんの比較がなされたんだ。この5年でC#は本当に成長した。今日はバージョン3.0の話をするんだし、2.0はリリースされようとしてるし、1.0と1.1はもうリリースされてる。

追跡調査を見れば、.NETは利用率でJavaと少なくともクビ差の勝負だ。C#は広まってる。今も成長中の言語だ。他の新言語とは対照的にね。実際僕は嬉しいんだ、この位置を占めたことがね。この2つのプラットフォームにはいくつかの大きな違いがある。つまり、.NETは何よりもWindows開発環境だってこと。そしてそれが異なったビジネス戦略の原因になっている。ねえ、僕らはC#と.NET Frameworkの中核に関する標準化活動に参加したよね。今はC#標準のバージョン3.0が存在する(注:ECMA-334ISO/IEC 23270)。

まあ彼らが3.0と呼んでるのは僕らの2.0だからちょっと紛らわしいけど。

Osborn:

それは後で聞くつもりだった。

Hejlsberg:

番号付けについてはちょっと不幸なことだし、何とか直すべきだ。でも標準は定められて、サードパーティの独立実装もある。Monoはすぐ思い浮かぶ例だ。だから閉ざされたプロプライエタリ戦略というだけではない。

この5年でMicrosoftは大きな方向転換をしたとも思う。透明性やコミュニティ参加、オープン性などについて。僕らが顧客とやってる対話の種類は5年前と比べても本当に本当に違っているし、10年前と比べたらもう天と地だよ。で、業界全体が、ブログとかオープンソースとかですっかり入れ替わってて、重力の中心みたいなのが、かつてよりもずっと個々の開発者や個人に移っているんだ。

コンポーネント指向言語としてのC#

Osborn:

(2000年にC#を世に送り出したとき、)君の箇条書きの一番目は、これが本当にコンポーネント指向の言語だったってことだったね。その見方は5年間で変わった?

Hejlsberg:

うーん、たぶんそれ以上のものになった。でも相変わらずコンポーネント指向言語として特徴付けられるはずだよ。プロパティやメソッド、イベント、日々のプログラミングの基盤になっている中核を思えばね。あの頃は、そして今はよりずっと、プログラミングは道具の支援をとても受けているし、道具はデザイン面のプログラミングモデルを持つ傾向にある。コンポーネントを配置して、修正し、裏側にコードを書いて、プロパティを設定するような。

いつも思うんだけども、とっても重要な概念だから、言語の中で一級の扱いを受けたがるんだ。そしてそれがC#で実現したことだよ。本当に正直言って、C#にプロパティがあることに対する不満って聞いたことがない。話題にすらならないことだ。わかるよね。単に「うん、うん」だけ。完璧に自然なことと考えられてるんだ。

ある意味、僕らがいつもやるようなことに一級の扱いをするっていうこの発想は僕にとって本当に大事なんだ。いろんな方法で同じことをしていて、LINQつまり言語統合クエリもそうなんだよ。プログラミング言語の中でクエリの記法に一級の扱いをする、これはみんながクエリ好きだからだ。何かを表現するための宣言的な手法では、ループやIF文の山を書いたり、その類のことを手作業でするよりもずっと高いレベルでできるんだ。

Osborn:

LINQの話を突っ込みたいけど、言語間の比較に戻ろう。Tony Goodhew がインタビューで言ってたけど、プログラミングでは2個以上の言語が使われることが多いことがMicrosoftの研究で分かったって。そしてそこには所詮シンタックス・シュガーなんだみたいな気分があるそうだ。君は自分が一番快適な言語を選ぶけれど。

それは変わったと思う?僕らはもうそんなこと言わないけど。

Hejlsberg:

そうだね、僕らはそんなことはしない。でも結局は文法じゃないか?ていうか、そうじゃないのなら、やりたいことについての抽象的な文法ツリーを記述したXML文書をやり取りしているだろうし。それも文法ではあるんだけど、プログラマーには絶対使いづらいよね。で思うんだけど、プログラミング言語って特別な位置を占めるもので、話し言葉によって自分を表現するのとちょうど同じ感じだと思う。プログラミング言語も同じだね;自分を表現する手段だ。

文法はプログラミング言語の現われで、実際いろんな意味で、プログラムをどう考えるかみたいなことに影響する。だから文法は無視できないし重要なんだと思うよ。

Osborn:

その点ではC#の特色は何かな?特徴を言ってもらえる?

Hejlsberg:

まず、さっき話したコンポーネント指向のことはとても重要だ。それと、何かする上で複数のやり方がないようにしようとしているんだ。常に文法的な要素同士の相乗効果を見つけようとしてる……言いたいことを的確に説明するのは難しいな。でもたとえば言語統合クエリ(LINQ)だよ。拡張可能なモデルはメソッド呼び出しに変えてしまうことだ。君たちがwhere句、orderby句、select句を含んだクエリを書いたら、僕らはそれをクエリ対象のコレクションに対するWhereメソッド、OrderByメソッド、Selectメソッドの呼び出しに変えてしまう。そしてクエリの中に書いた式はラムダ式の引数にしてそれらのメソッドに渡す。

そうしてクエリは単に連結したメソッド呼び出しとなる。でもクエリの文法のほうが読みやすい。構文的には単なる化粧板だとしてもね。即座にメソッド呼び出しに置き換えられるのは、foreachループが「whileループでの列挙オブジェクト取得」に置き換えられるようなのと同じだ。でも高レベルで考えるのには便利だ。言ってることは分かる?

Osborn:

うん。

Hejlsberg:

そういう意味では、文法は問題解決の方法に深く影響している。起こっていることに対する影響は意味論的には全くないとしてもね。

Osborn:

うん。出版社の立場から言うと、ぼくら自身のデータ追跡からわかったんだけど、C++が、おかしな話だけど、持ちこたえているんだ;実際、書籍の売り上げは若干上昇してて、反対にVBはたしか去年20から25パーセントほど落ち込んだ。C#はとても安定している(注:でも横ばいだ)。

Hejlsberg:

うん。

Osborn:

だから明らかに、僕らからみれば、VBからC#へ(注:あるいは別の言語かもしれない)の移行が見られる。でもC++は特定分野で最適なようだ。

Hejlsberg:

そう。VBとC#は同じプログラマー層にとってとても魅力がある。C++はマネージ空間で動作もするけど、C++の核はアンマネージコードを書くことにある。低いレベルのプログラミングにね。これは一般論ってことは分かってるし、もちろんテンプレートやSTL(注:標準テンプレートライブラリ)が使えるし、何かを軽視しているつもりはない。ただ、C++の幅広い立場や顧客は、違った種類のアプリケーションを書くもんだってこと。一方でC#とVBとは同じ層にとても気に入られる。

Hejlsberg:

だから別に驚かないよ、C++が……

Osborn:

マネージコードを書くのにはC++は選ばないだろう?

Hejlsberg:

個人的にはないね。それでマネージコードは書かない。マネージコードにならないようなコンパイラを書いたりするなら別だけど。でも原則的には、年が過ぎるごとに、マネージコードを書く理由は強まっていると思うよ。単純に、ハードウェアは現時点でさらに強力だし、トレードオフも、間違いなくそんな大きなものではないけど、でも「CPUパワーとメモリをちょっと犠牲にして、生産性を大幅に上げよう!」っていうトレードオフも結構あるしね。これは本当にやる価値のある主張だと思う。ますます本当のことになってきてるから。そして、マネージコードの世界は日々豊富になってきている。明らかにすべての技術革新が起こっている場所だし、大量のエンタープライズアプリケーションが今書かれている場所でもある。

ジェネリクスとC#

Osborn:

ちょっとはバージョン2.0の話もしたほうがいいかな。まちがいなく、ジェネリクスは長い間待たれていた。

Hejlsberg:

そうだね。

Osborn:

C#のジェネリクスは他言語のと比べて何が違うの?

Hejlsberg:

それはC#とJavaで何が違うのかと聞いているような。明らかに。

Osborn:

正しい。

Hejlsberg:

まず、2.0にジェネリクスを入れられて嬉しい。ジェネリクスはいろいろな意味で、僕らがC# 3.0でやってみせたすべてのことの深い要因なんだ。ジェネリクスが静的型システムにもたらす新しい深みといったら本当に奥深くて、あらゆる可能性がそれによって広がる。言語統合クエリも、ジェネリクスなしにはなし得なかった。そういう意味では、面白いことの深い要因だね。それにとても実際的で、実務上の問題も解決してくれる。

ほら、型はしっかり付いているほうがいいんだ。だってもっと多くの誤りを早くに見つけられるから。それにコード生成も向上する。だって、プログラムで使ってる型の堅牢性を確かめるための実行時に動的なチェックが少なくてすむから。

さて、JavaとC#を比べたら、文法的には、ジェネリクスの実装はとても近く思える。どっちもC++のテンプレートみたいだ;C++の遺産がそこにあるのが分かる。

でも表面を引っかいてみたら、その下は実際にはとてもとても違ってる。最大の差は.NETのジェネリクスはただの言語機能ではないことにあると思う。C#のはCLRや.NETの型システムに深く解釈される。だから実行時の表現もある。

Javaはジェネリクスの実装に違う戦略を採用して、簡単に言えば、Javaのはコンパイル時の機能にすぎない。コンパイラはコードからジェネリクスに関するすべてを取り去ってしまい、出力は単なるオブジェクトだ;型付きのパラメータはすべて効果的にオブジェクトに置き換えられる。Javaでは、実行時は、ジェネリクスはどこにもない。VMを変更しなくても動くっていうところは面白いけど、びっくりするような制限とか、守らなければならないルールを抱え込むことにもなってる。こっちではジェネリクスを使ってパフォーマンスが増加するけどそれも得られない。だって実行時にはジェネリクスがないから、List<T>から何か取り出すときにはやっぱり実行時の動的なチェックやらダウンキャストやらをしなきゃいけないんだ。

だけどもっと難解なとこがあると思ってて、それは、ジェネリクスの実行時表現がないから、コンパイル時のコードから実行コードにする際に情報が失われるってこと。コンパイル時には顧客のリストを操作しているつもりだったかもしれない。いざ実行時にオブジェクト型顧客のリストを渡されたなら、それからは単なるオブジェクトしか取り出せないし、このリストがいったい何のリストか知りたくても、術がない。だってリフレクションは、削除されたジェネリクスについては知らないんだから。

ってわけでこの仕組みにはこういう奇妙な穴がある。そして動的なコード生成と検査……動作中のコードやら動的な振る舞いやらについての……にますます頼るようになっている世界においては、これは実際に、僕にとっては、Javaのジェネリクス実装におけるおそらく最大の問題点なんだ;つまり、動作中のプログラムについて本当には表現できないということがね。

Osborn:

ってことは、.NETのジェネリクスはその情報を握ってて……

Hejlsberg:

ああ、もちろん。もしobject型のList<T>があれば、「君は何?」って聞ける。そしたらそれは「私は顧客のリストです」って言う。「私はList<T>で、Tっていうのは顧客です。」ってね。そしたら僕は「じゃあ、僕にList<T>を表すSystem.Typeオブジェクトをくれないか。そして実際には、Tを注文に結び付けてくれ」と言える。そうすれば僕は自分自身をList<Order>に変えることができて、インスタンスを生成できる。コンパイル時にできることは何だって実行時にもできる、リフレクションを使えばね。そしてこれは超強力なんだ。

Osborn:

匿名メソッドの追加はどうかな?アナウンスされたときを思い出すと、僕は本の著者たちと話し合っていて、匿名メソッドについて本文に追加しなきゃって言ったんだけど、なぜそうしろって言ったのかよく分かってなかった。今は匿名メソッドを利用するケースをいくつか分かってる。(これを読んだ人たちはそこを知りたがるだろう。でも、匿名メソッドが、ジェネリクスのように、C# 3.0の新機能の元になっている仕組みを知るのもまた興味深い。)

Hejlsberg:

ああ、まさに。それに、正直、まずは認めるべきときに認めておくよ。僕は完全に新しい何かを発明したわけじゃない。全てはラムダ式とかラムダ計算とか言われるものに基づいているんだ。それは関数プログラミングの世界に何十年も前から存在していた。でもなぜか、主流のプログラミング言語においては日の目を見てこなかったんだけど。

そして幸運にもC#がそれをやった最初になった。僕らはそれを進化させることにすごく一生懸命になっていて、その結果はC# 3.0で見ることができる。僕らは匿名メソッドを、今はラムダ式と呼んでいるものに進化させた。そしてラムダ式は高機能な型推論で包んだ。だから以前は手動で書かなければならなかったもろもろを書く必要はもうないんだ。

Hejlsberg:

どうしてそれが重要なのかを、ある例を挙げて説明しよう。C# 3.0で僕らは言語統合クエリ(LINQ)のこんな記法を取り入れた。そして実際、僕らがやっていることは、APIとしてクエリ言語を構築することを可能にするものだ。つまり、WhereとかSelectとかOrderByとかGroupByといったメソッドを元にしてね。もしコレクションがWhereやSelectやOrderBy、そしてGroupByメソッドを持っているなら、それらを一続きに組み合わせて、それらを元にクエリ言語全体を組み上げることができることが分かってもらえると思う。

でももし匿名メソッドやラムダ式をサポートしない言語でそれをやることになったとして、どうやってWhereメソッドを実装しようか考えたら、さあ、引数として述部を受け取りたいよね?個々の要素に適用するテストだよ。言っていること分かるよね?つまり、list.Where(ほげほげ)って書きたいんだけど、渡したい「ほげほげ」がテストだね。

でも通常の意味でのパラメータとは似ていないんだ、ただの真理値として渡すんじゃないから。それだと明らかに前もって評価してから渡すことになるからね。そして欲しいのは真でも偽でもなくて、テストそれ自身を渡したいんだ。言っていること分かるよね?

Osborn:

ああ、述部は渡した後に実行したいんだよね?

Hejlsberg:

そう。そして望むものは実際には、実行できるコードへの参照が欲しいわけ。いいかな?Where演算子に渡す関数参照かメソッド参照が欲しい。そしたらWhere演算子はテストしたい個々の要素に対してそのコードを実行して、そして、このテストが真になるような要素全体を返すってわけ。そしてSelect演算子(i.e.射影)がどう動くかを見ても同じだ。っていうのは、要素が与えられて、ある要素を別の要素に変えるメソッドが与えられるって感じ。これが射影。

OrderByは、2要素を比較できる何かが与えられるって感じ。もう一度言うと、それはちょっとしたコードだ。だから実際、プログラミング言語の表現上で足りなかった物は、コードをパラメータとして渡す能力なわけ。

Osborn:

それが意義か……

Hejlsberg:

そしてこれが、ラムダ式と匿名メソッドでできることの概略だ。ところで、ラムダ式と匿名メソッドは、実際は同じものを2つの言葉で呼んでいるだけなんだ。唯一の違いは、文法はどう見える?ラムダ式は文法が大幅に進化している。でも内側は、同じものを現している。どちらもメソッドを生成するんだ。インラインのメソッドだね。

Nullable Typeの重要性

Osborn:

ジェネリクスや匿名メソッドの他に、2.0で注意すべきものって何?

Hejlsberg:

Nullable Typeかな。これもとても重要な進歩だ。だってデータベースの世界と汎用プログラミングの世界とに対象性を持ち込む一歩だからね。ええと、この二世界の重要な対応付けについて話すのはかなり難しいけど、一方は、データベース界だけど、これは完全にヌル可能な型に基づいている。そしてもう一方はそういったものを全く持っていない。

Hejlsberg:

そしてもちろん、自分ででっちあげることは可能だ。

Osborn:

そのときやらなきゃいけないことは……

Hejlsberg:

……汎用プログラミングの世界では、まあ、例を挙げればボクシングでやることが多い。それか、値を保持するようなオブジェクトをわり当てて、値を持たないときにはnullを使う。そういうのはJavaでうまくやる方法だ。でもそういうことをするととても高くつくんだ。なぜってnullにもなりうる整数値を表現するためには、Javaで実現する典型例はIntegerラップクラスを使うことで、そしてすべてのint値に対してインスタンスを割り当てて、null値には単にnullを使うことになる。

Hejlsberg:

でも各int値に対するメモリ消費量は4倍になるし、遠回りになってしまう。だからそれについてコストが多くなる。でもC#のNullable Typeでは、値型をnullにする能力を効果的に与える。でもオブジェクトをヒープに割り当てて実現してるわけじゃない。Tとboolを結びつけたジェネリック型で実現している。これがNullable<T>と呼ばれるもので、内部には2つのフィールド、Tとboolを持っている。

でもNullable<T>自身は値型だ。だから実際にはスタックに保持するかインラインで割り当てるかで……それ以外の方法による解決法よりもメモリ処理の観点からはずっと効率的だ。さらに、ヌル可能をサポートする言語文法もある。クエスチョン・マーク(?)を型修飾子にしているんだ。

だからintが整数値のとき、int?はヌルになり得る整数値で、intからヌル可能intへの変換は暗黙に行われる。そして一方でnull例外を投げるような他の明示的な変換もあり、……ヌル可能型を適切な概念として深くサポートしている言語に自然に期待するようなことがらと同じだ。繰り返しになるけど、日常使っているものごとに一級の扱いを与えるっていうのはこういうことだ。

そしてまた、言語設計者である僕にとっては、見ているのは、「人々はここで何をやっている?そして一級の扱いを与えることを考えなきゃいけないのは何だ?」だ。

Osborn:

じゃあ、C#こそが「ひとつの言語はすべてを統べ」なの?

Hejlsberg:

(笑)違う違う、そうじゃ、そうじゃない。他の言語のほうがもっと適していることもたくさんあるよ。C#は、核の部分は、強く型付けされた言語だ。そしてあることがらに関しては動的型付けの言語のほうがより適しているよね。コードを数行書く時には、まず最初に山ほど宣言しなきゃいけないのは嬉しくなくて、単純に試し始めたいだけだったりとか。でも人気のある言語の仲間の中では、間違いなく、できる限りのことをやろうと思っているよ。

Osborn:

2.0に関しては、Microsoftの実装に見られるような変更も標準として提案されるのかな?

Hejlsberg:

2.0の?

Osborn:

2.0の。

Hejlsberg:

うん。標準は「第3版」と呼ばれることになるはずだけど、これは実際には僕らが2.0と呼んでいるものだ。

Osborn:

じゃあ、加わった変更については、Microsoft実装だけのものは無いってことかな。

Hejlsberg:

うん。C# 2.0の全部の言語機能はECMAに提出されているし、標準化の手続きが進められている。そしてまもなく、コミュニティによる投票が適切に行われると思っている。現段階では手続きだけの問題だね。(注:これはすでに実施された。 “C# and CLI Become More Powerful” を見よ。)

Osborn:

じゃあたぶん年末ごろになるかな?

Hejlsberg:

うん。

Osborn:

3.0に関していえば、(ブロガーやコラムニストによって)書かれていることを読んでいて思ったのは、なぜ(LINQが)重要なのかの真意は理解されつつあるようだ。ただ、変更点について君がもっと注意してほしがっている何かを私たちは忘れてやしないかと思うんだけど。

Hejlsberg:

いや、大体みんなが理解していると思うよ。だってほんの一例だけ理解すればよくて、それで「ああそっか、これ必要だな」ってなるから。オブジェクトや関係データやXMLにクエリを渡すための手段が単一にできる記法っていろんな意味でみんなが望む聖杯だろうし、それに向かってかなりのところまで前進できたと思ってる。今やっている言語拡張やLINQプロジェクトによってね。

C#とLINQ

Osborn:

僕が理解するまで2つのプレゼンが必要だったんだけど、それぞれ独立して眺めても面白いC#の新機軸の集合と、その上にくる層が実際にはあるってことだよね。それについてもうちょっと話をしてもらってもいいかな?

Hejlsberg:

うん。君はかなり微妙ないい所をついてると思う。いろんな方法をとることができたんだ。そして君が考察したことについては、うー、プログラミング言語内にクエリを持てたらすばらしいって僕らが同意するとしよう。こう考えたのは僕らが最初ではない。そうすると僕らの手法とかつての手法とで異なるところって何だろう?

もし、たとえば埋め込みSQLとかSQL/Jとかと比べたとして、今回の拡張も同じようにプログラミング言語にクエリを持たせられる。でもそういった手法がやってることは単にある言語内に別の言語をホストすることだけだ。Javaの中にSQLをホストしているだけ。埋め込みSQLならCの中にSQLをホストしているだけ。わかるかな?いくつかの抜け道によってある世界から別の世界に連れて行っている。2世界を結び付けるにはかなり乱暴な仕組みだ。

だからクエリ言語に一級の扱いを与えてはいない。ただある言語を別の言語にくっつけただけ。僕にしてみれば、もっとよい手法っていうのは――大げさに言えば――欠けているものを見つけだして理解すること。たとえばC#なら、C#自体がクエリ言語であるうえで不自由を感じないためにね。

というのは、僕の考えは、まあ昨日も言ったけど、C#がクエリについてはSQL Server 2000や何かとしか連携しないなんてことになるなら、それはC#の死だろうってこと。SQL Server 2000に問題があるなんてつもりじゃないよ、もちろん。でもプログラミング言語としては、それがなくても一歩前進しないといけない。いつも問題のクラスについて考える必要があるんで、特別なインスタンスについてじゃない。いいかな?お客様はいつもやってきてはこれが問題のインスタンスなんだっていう。で僕がいつも考えるようにしているのは、「えーと、今話していることのクラスはなんだろう」だ。言ってることはわかる?事実上は、C# 3.0とLINQプロジェクトでの手法における大きな違いというのは、言語に追加した機能と、それらの機能の利用法のある一例,、たとえばDLinqやXLinqや標準クエリ演算子なんかとは完全に分離されているということ。

そして僕らが最良のことをやってないと感じた誰かが別のAPI集合を書くことができたとして、C# 3.0のすべての機能はやっぱり適切なんだ。だから彼らが彼ら自身の利点を主張しても、やっぱり2者の相乗効果こそがすべてを動かしているんだ。

Osborn:

C#のプレゼンでは、拡張メソッドのところでたくさん「おお!」とか「ああ!」を聞いたよ。そして君が通り過ぎたほかの革新のところでもね。それらはデータ自身とは無関係だったかな。

Hejlsberg:

そう。僕らがやってることには深い理由があるけど、それらには別の良い利用法もある。ラムダ式を例に選んでみよう。ラムダ式から式ツリーを生成する機能はイベント通知システムで多くの面白い利用法がある。システムにトリガーを渡したいんだけど、そのトリガーは実際にはシステムに与えたい述部で、述部はシステムが判断を下すことができる形式で、とかなんとか。

ルールエンジンとか、制約処理システムとか、これを使ってできることって他にもこんなにたくさんあって、今の話は氷山の一角を見てるだけなんだ。山ほどあると思うね。いろんな意味で、多くの人々が関数プログラミング言語に興味を持っているのはそういうわけだし、学問世界で熱心に議論してるのもそういうわけだ。プログラミング言語にこういった能力を手に入れたとたんに意味を持ち始める問題全体のクラスがあるんだ。

Osborn:

プレゼンの時しゃべっていた内容のひとつは確か、C#として組み上げる方法は通常のSQL型のクエリに比べてメモリ使用量とかその類のことで多くの長所があるってことだった。これは話のネタになる?

Hejlsberg:

えーと、そのときは2つのことを話したと思う。まず最初は、SQLは明らかに関係データでしか動かないけど、今僕らがやろうとしているものはもっと広い。オブジェクトに対するクエリ言語だ。そしてそのオブジェクトが表すものは関係データでもいいし、単にあるクラスのメモリ内インスタンスでもいいし、XMLでもいい。

だからその意味ではもっと広い。メモリ効率については、あの時はXLinqのAPIについて話したと思う。XLinqは2つのことをやってくれると思っていい。XMLに言語統一クエリをもたらすし、XMLDOMでの10年に及ぶ経験を生かしている。XMLDOMは人々が今日アプリケーション内で利用しているXML APIの最たるものだ。

そしてXMLDOMには当時は適切に思われた設計判断が山ほど下されているんだけど、今にして思えばそんなに重要なことではなかったって気づいたんだ。だけど不幸なことに、とある特別な機構を持たなければならないからメモリ消費量は倍増している。あれだよ、属性として未解析の実体を保持する機能みたいな;XML専門用語でしゃべるオタにしか聞こえないとは思うんだけど、これってコンマ001パーセントしか必要にならない、まさに奥義機能って感じなんだ。

にもかかわらず、これを表せなきゃいけないっていう事実が、属性を保持するための内部構造に深く影響している。属性を単に文字列で保持するんじゃだめなんだ。だって内容要素のリストや何かにもなれないといけないから。そしてそういったことが積もり積もって、日々支払うオーバーヘッドの山になる。決して使わない機能であってもね。

だから僕らは賢明な判断をしたんだ。人々がどのようにXMLを使うかについて、今はもう適切な情報を持ってるよね。その情報はXLinq APIの根底にあるデータ構造を深く決定付けた。それによってある大きなメリットがある。プレゼンではメモリ消費量を30〜50%削減したと話した。そして一般的には、それってパフォーマンスの向上とも同じだ。だってほら、メモリを少ししか使わないなら、経験則としてはパフォーマンスも良くなるからね。

Osborn:

3種類のクエリに関する基本的な文法は実際にはC#のものと同じだ。別々のものとしてダウンロードする必要があることはどう考えればいいのかな。DLinqと、XLinqと、標準クエリ演算子。これらは全部同じパッケージに含まれるの?どうしてプレゼンの時みたいな区別をしているの?

Hejlsberg:

これはクラス対インスタンスの質問だね。解決しようとしている問題にはクラスがあって、それはオブジェクトあるいはオブジェクトのラッパーに問い合わせる能力のことだ。というのは、実際ある意味では、オブジェクトのインスタンスが存在している必要はないから。この問題のクラスは、言語統合クエリとは何についてのものかということだ。それは表記法で、クラスが宣言されていくつかのクラスのインスタンスがあれば、それのプロパティやあれのプロパティや何かを参照したいときにそれに対するクエリを書くことができるんだ。

そしてそのときに実オブジェクトの実インスタンスを持っている必要はない。それは、オブジェクトはプロキシであってもよいからだ。これがO-Rマッピングの仕組み。いい?そしてそれはデータベース内の全注文に対してクエリのように見えるものを書くことができる能力を与えるものだし、その時にはどの注文も実体化してなくていい。で、オブジェクトはこんなようにとても強力だから、大げさに言えばいろんなことを山ほど実際にできるんだ。

でも根本では、それはO-Rマッピングを使って実装できる。だから君が見ているものは、実際には僕らが解決しようとしている問題クラスがあって、その上で君はその問題クラスのとあるインスタンスを見ているんだ。そのひとつが僕らが標準クエリ演算子と呼んでいるAPIだ。それはここでは単に関係演算的に完全な階層型クエリ言語のことなんだけど、IEnumerable<T>を実装するものだったら何にでも使える。

そして話は変わるけど、.NETのすべての配列やコレクションも実装してる。だから言わばこのシステムを使ううえでの障壁は超低い。即効性満足感効果だよ。ドカンと問い合わせできる。どんなコレクションでも、メモリ上のどんな配列でも、その他もろもろでも。でもこうも言える。ほう、そりゃいい、でも関係データだってあるよね?って。さあ、関係データだけど、言わば盲目的に、単純に全テーブルをメモリに突っ込んでしまえば問い合わせのために標準クエリ演算子を使えなくもない。でもこれはさすがに受け入れられないよね。

だからこれこそ解決したい問題の別のインスタンスで、実際には異なる実行文法が欲しくなる。問い合わせをメモリ上で実行する代わりに、式ツリーを捕まえておいて、データベースにSQLの形で送り込みたい。だから事実上は、式ツリーを捕まえて、SQLに翻訳して、データベースに送信して、結果が戻ってくるのに合わせてオブジェクトを生成する、と。奇術だよね。「うわあ、問い合わせがまったく同じに見える!」さてはて、実行の方法は完全に異なっているんだ。

そしてXMLについてはね、更に違った世界なんだ。だってデータ構造の種類がまた違うものについて話しているんだから。XMLオブジェクトモデルってあるよね、CLRのオブジェクトよりも弱い型付けの。それに文法や何やらも違う。でも基本となるクエリ言語は同じように適用される。

だからそういったように考えるべきなんだ。3者は同じ問題クラスの別インスタンスなだけ。でも微妙な違いがあって、そして、APIは問い合わせに対応可能だ。永続化に対応可能だったり、リモーティングに対応可能だったりするのと同じようにね。問い合わせはAPIの新しい能力になるんだ。

Osborn:

そうすると、別パッケージによって受け取るものは、目的別のAPIセットで……

Hejlsberg:

それらは問い合わせ可能な別APIだ。うん。だからそれがそれらAPIの属性なんだよ。問い合わせるんならね。

Osborn:

理解した。ある2人から聞いたんだけど、世の問題の90%は解決したと君が言ってたって。残りの10%って何?

Hejlsberg:

(笑)コンピューティング一般において、みたいなことを聞きたいの?

Osborn:

クエリに関係してだよ。C#におけるアプローチではだめで、何か専門的なクエリ言語がまだ必要だったりとか。

Hejlsberg:

うーん、そりゃ僕らはとっても広い網を投げようとしていて、そしてできる限り多くを引き上げようとしているとは思う。けど僕は、クエリに最大最強のものを構想として期待してはいない。あのー、明らかにSQLは長い間役に立つものであろうとしていた。そして僕はSQLを排除するとかXQueryを排除するとかなんとか考えるほど馬鹿じゃない。いやまったく。僕らはそれら技術を補完しようとしてるんだ。

.NET Framework上でコーディングする時に利用可能なすばらしいツールを目指している。でもおかげで、APIを設計するときにはいつも出てくる別の設計原則に悩まされる。

たとえば、DLinqがあれば言語統合クエリを書けてすばらしい。なぜならすばやくできるし、高速だし、生産性も上がるし、他にもいろいろ。でもユーザー定義の関数とか呼び出しとかストアドプロシージャとか何かを使った奥義的なSQLクエリを書きたいときもある。ほら、たまにそういうことをやらざるを得ないような場合っていつだってあるよね。そしてDLinqのAPIの一部はSQL用の脱出口と捉えることができるものだ。だから言語統合クエリも書けるけど、ExecuteQueryという名前のメソッドだって用意している。そのメソッドはSQLクエリである文字列を引数に取るんだ。

そして型パラメータを使って結果の型を書くようになる。だからExecuteQuery<Customer>(“select * from customers where …")って書いて、SQLクエリ内のユーザ定義関数を呼び出せる。そしたら僕らはその結果をCustomer型のインスタンスとして扱う。だからDLinqの残り全部の機能は依然として使える。参照アイデンティティとか、変更追跡とか、変更をサーバに書き戻す機能とか、いろいろ。

Microsoftでの以前の仕事では、WindowsフォームAPIの設計にも関わっていた。そしてそこでは、例えば、裏に隠れたウィンドウハンドルを得たり、単にUser32.dllの関数を直接呼び出したりできる脱出口もあった。だって時々は必要だから。いつだって、基礎となっている技術に戻ることができる脱出口があるべきなんだ。

大抵そうだと思うんだけど、カプセル化の目的は隠すことだって考えるよね。それはカプセル化の目的じゃないんだ。目的は何かを簡単に使えるようにすることで、下にあるものを隠すことじゃない。

Osborn:

出したネタ全部をやり遂げちゃったんだけど、次は何?未開拓領域は?

Hejlsberg:

うーん、そうだね、次は、C# 2.0の出荷、その後はC# 3.0の出荷(笑)

Osborn:

そうだ、期限を聞かなきゃね。CTPのリリースが……

Hejlsberg:

うん。

Osborn:

……イベント(PDC 2005)の時はみんなが触れる。

Hejlsberg:

うん。それにWebでも公開する。だからイベント参加者だけじゃないよ。誰でもダウンロードしてβ2に載せられる。だからWhidbeyのβ版、Visual Studio 2005 β2をインストールすれば、LINQプロジェクトのテクニカルプレビュー版をダウンロードして追加できる。たった6MBのダウンロードだ。ドキュメントはたくさんあるよ:LINQプロジェクトの概要、C# 3.0の言語仕様、標準クエリ演算子の仕様、DLinq、XLinq、それにたくさんのサンプル。だから本当に単にインストールするだけで腰を落ち着けて完全に理解できる……

Osborn:

そう、君たちのチームが載せてた101のサンプルにはびっくりしたな。

Hejlsberg:

うん。その小アプリはすごく良かった、みんなにはすっごい役に立つから。だってプログラマーはコードを見たいもんだし、コードを書いた結果も見たいもんだ。そして小アプリはまさにそれのためのものだからね。

Osborn:

その通り。そしてβ版が出る;βのスケジュールはOrcasのスケジュールに大体一致している、のかな?(注:OrcasはVisual Studioの次期メジャーリリースで、2007年上半期のいつかに予定されている)

Hejlsberg:

えーと、Orcasの製品群の波にこの技術をぶつけるつもりだ、うん。それが大体、今の時点で可能な限り詳細な話だ。Visual Studio 2005の最終出荷版を出したら、それと同期するようにLINQプロジェクトの技術プレビューを改める予定だ。だから出荷した製品の上でLINQプロジェクトを使える。以上が、僕らが知ってる、やろうとしてることだ。

でもOrcas製品群の波が正確にいつになるかとか、そういうことを言うこととはできない。それに両者(アナウンスしたC# 3.0およびLINQ拡張)のどちらも、100%が実現するとは言えない。でもそれを目指してるのは間違いない。

Osborn:

まとめると、みんなには何について覚えておいてほしい?――プログラマーは2.0と3.0で今から何をすればいい?

Hejlsberg:

2.0では、ジェネリクスと強い型付けをプログラムに取りいれて利用して欲しいね。それがいわゆるWin-Winの状況だ。ケーキをとっておきつつ食べもする、みたいな。だからアプリケーションで利用して欲しい。3.0では、僕らが今公開している技術プレビューを見てみるのが大事だ。今進化しつつある機能を実際に垣間見れるわけだし。

それに、この技術についてフィードバックをくれると有り難い。僕らは本当に、言っておきたいんだけど、この言語に深い革新を成そうとしている。それはつまるところ、新しい土地を歩いているってことだ。だから、正しい方角に向かっているのかについて、これまで以上にフィードバックが必要なんだ。

Osborn:

それにはどうするのが一番良いのかな、取り組みたい人たちにとっては?

Hejlsberg:

LINQのプレビュー版をインストールする時、MSDNのフォーラムへのリンクがある。僕らのチームメンバーの多くはブログを開いてる――そっちでのフィードバックの機会も多々ある。それに、製品のバグを実際に入力したりとかできる、ladybugバグ追跡システムもある。だから、フィードバックする機会はたくさんある。

Osborn:

素晴らしい。

Hejlsberg:

電子メールでもいいよ、その件では。

Osborn:

どうもありがとう。また5年後に話せれば良いね。(笑)