C#/Visual Stduio.NET/.NET Frameworkの実像を探る

2.何はともあれ、C#プログラミングを体験しよう

川俣 晶
株式会社ピーデー
2001/01/11

Page1 Page2 Page3 Page4

Windows Formsとダイアログボックス

 実際にVS.NETを軽くさわってC#で書いてみた。まず、ウィンドウ・アプリケーションを記述するWindows Forms(以下WinForm)と呼ばれる機能をベースとしたプロジェクトで遊んでみた。

 IDEに含まれるフォーム・デザイナーの使い勝手は、まさに、Visual Basicという感じで、けして悪くない。だが、Visual Basicと異なり、フォーム上にコントロールを貼り付けると、それが即座にソース・コードに反映される。具体的にコントロールをフォーム上に生成するコードが、ソース・コードに挿入されるのである。このとき、コントロールの実体を保持するメンバ変数も自動的に生成される。ここが、Visual Basicとの最大の相違点と言えるだろう。Visual Basicでは、ユーザー・プログラムとして見えるのは、プログラマが自分で書いたグローバルな宣言やプロシージャ、そしてIDEが生成するイベント・ハンドラなどに限られ、コントロールなどはソース・コード上に文字としては現れない。もちろん、ファイルとして保存して、テキストエディタで開くと見えるのだが、IDEの中で、ソース・コードの一部としては見ることはできない。これに対して、VS.NETのC#プロジェクトでは、コントロールを保持する変数も、それを生成するコードも明示的にソース・コードの中に組み込まれる。このスタイルは、実は、Visual J++にそっくりであり、IDEがVisual J++の直系の子孫であることを連想させる。

 では、これをVisual C++と比較するとどうだろう。Visual C++では、フォームをデザインするのではなく、ダイアログボックスをデザインすることになる。ダイアログボックスそのものは、OSがサポートするダイアログボックス機能を提示しているだけで、Visual C++が全面的に管理しているわけではない。このダイアログボックスと、VS.NETにおけるWinFormを比較すると、極めて大きな構造の違いがあることが分かる。最大の相違は、ダイアログボックスでは、それを処理するコードと、ユーザーに見えるビジュアルの定義が完全に分離している点にある。VS.NETでは、どんなコントロールがどんな位置に生成されるかという情報と、そのコントロールに対するイベント処理が、1本のソース・コード上にある。しかし、ダイアログボックスは、どんなコントロールがどんな位置にあるかは、リソースに記録されるべきものであり、ソース・コード上にはない。

 このような、リソースとソースの二重構造は、国際化を容易にするために考えられたものだ。ある言語(プログラム言語ではなく日本語や英語などの自然言語)で書かれたプログラムで別の言語をサポートするには、リソースだけ書き換えればよい、と言うのが、1つの目指すべき理想と言える。その際、メッセージの内容を入れ替える必要があるのはもちろん、メッセージの長さが変わるため、コントロールの配置も変更を余儀なくされる。そのため、コントロールの位置情報も、リソース上に存在しなければならないという制約がある。

 だが、この2重構造は理想論としては素晴らしいのだが、実際に扱うのは面倒である。ソース・コード、リソースのソース・コード、そして、両者から参照されるヘッダ・ファイル(ID番号を定義する)の3つのファイルを矛盾なく統合して扱わねばならないのだ。しかも、それだけ苦労しても、現実にリソースを差し替えるだけで国際化できることは多くない。たいていの場合、ソース・コード上に言語に依存する情報が残ってしまい、それを書き換える必要が生じるからだ。そのようなことから考えて、現実的にはソースとリソースを分ける必要はないと言えるのかもしれない。

 だが、すっきりしないものが残り、筆者には1つの謎となっている。

C++のプロジェクトでダイアログボックス・デザイナーを使用しているところ

Visual C++のダイアログボックスは、プログラムの国際化を容易にするため、ダイアログボックスの見かけを定義する部分(リソース・ファイル)と、それらを処理するプログラム・コードを完全に分離していた。これに対しVS.NETのWinFormでは、ダイアログボックスで使用するコントロールの情報や、そのコントロールに対するイベント処理がすべて1本のソース・コード上に記述される。
  VS.NETでは、ダイアログボックスにコントロールを新たに配置したり、位置やサイズなどの属性を変更したりすると、それらの情報がソース・コード上に自動的に反映される。

 しかし、Visual Basicとの比較で言えば、VS.NETとC#の組み合わせは、非常に良好な使い勝手だと感じられた。フォーム・デザイナーの使い勝手は似ているが、プログラム言語としての側面は雲泥の差がある。強い型付けを基本とするC#は、どんな型でも入れられる魔法の箱を使わないのが基本である。型を省略して宣言するとVariant型になってしまうVisual Basicとの決定的な違いだ。また、オブジェクトでも数値でも、同じ代入構文で書け、数値をオブジェクトにパッケージするboxing/unboxingの仕組みと相まって、同じ構文でどんなデータであろうと処理できる。このような特徴から、Visual Basicよりも、ずっと見通しがよく分かりやすいプログラムが書けそうである。

 ただし、前述したsetキーワードの件は、VS.NETのVisual Basicでは撤廃されるようだ、ということを付記しておく。事実上、VS.NETのVBは、VBに似た文法を使って書くC#という性格が強い。以下の画面写真を比較するだけでも、何となく分かるだろう。

Visual Basic 6のプロジェクト

フォームとしてダイアログボックスを開き、これに対してボタンやエディット・コントロールといった各種コントロールをマウスでドラッグ&ドロップして、それらのコントロールが操作された際の処理をイベント・ハンドラとして記述する。C++のようなオブジェクト指向プログラミングの知識がなくても、このように手軽にプログラムを作成できるのがVisual Basicの大きなメリットの1つだった。
  フォーム上に配置されたプッシュ・ボタン。左のコントロール一覧からマウスでドラッグ&ドロップすることで、コントロールを簡単に配置できる。
  のコントロールをマウスでダブルクリックすると、そのコントロールが操作された際の処理(このプッシュ・ボタンの例なら、ボタンが押されたときの処理)を記述するためのウィンドウが表示される。
 

VS.NETでのVBプロジェクト

これに対しVS.NETのVBは、CLR(Common Language Runtime)と呼ばれる共通の実行環境において、複数の言語処理系を対等な存在とし、それらを必要に応じて組み合わせ可能にするために、よりオブジェクト指向言語の流儀にのっとった記述が必要とされるようになった。これによりVBのプログラミング言語としての機能性は向上したが、代わりにVBの身上だった手軽さは失われてしまった。
  VBのコードの一部。Visual Basicの記述スタイルに似せているが、VS.NETのVB(VB.NET)では、オブジェクト指向の流儀をきちんと踏まえなければならなくなった。事実上VB.NETは、VBに似た文法を使って書くC#という性格が強い。

WebFormの衝撃と快楽

 WinFormでプログラムを書いていて、はたと気付いたことがある。それは、.NET Frameworkの中に、WebとHTMLのキーワードを冠した多くのクラスが存在するにもかかわらず、HTMLをレンダリングして表示するコントロールが見あたらないことだ。もちろん、Internet ExplorerをActiveXコントロールとしてWinForm上に貼り付けることはできるのだが、これは.NET Frameworkという1つの体系の外にある機能を使うわけで、.NET Frameworkを楽しむという趣旨には反する。

 そこで、いろいろな可能性を考えた結果、HTMLを生成してWebブラウザに送りつける方法なら行けそうだと気付いた。そのために、WebFormという機能が提供されている。これは、VBとはかけ離れた方法論ではあるが、Webブラウザという標準的なソフトウェアをユーザー・インターフェイスに使えば、クライアントはどんなOSであってもかまわないことになるので、むしろ自由度は増える。

 そのようなわけで、VS.NETから新しいWebFormのプロジェクトを生成したのだが、すぐにエラーで終わってしまった。WebFormのプロジェクトは、いきなり、ファイルのローカルパスではなく、「http://自マシン名/」の下に、ネットワーク上のリソースとしてプロジェクトを作成しにいったのである。うっかり、IISも何もインストールせずにOSをセットアップしていたため、プロジェクトがそもそも生成できなかったわけだ(本稿の冒頭で述べたとおり、当初テストはWindows 2000 Professionalにて行った)。そこで、IISをインストールして試みたところ、プロジェクトは作成できたが、デバッグ・セッションに入ることができない。そこで、1度パーティションをすべて消して、英語版のWindows 2000 ServerをインストールしてVS.NETをその上に入れ直した。今度は、ちゃんとIISを用意した上でトライした。その結果、やっとWebFormのプロジェクトを実行してデバッグ・セッションに入ることが可能になった。だが、とてつもなく重い。VS.NET、デバッグ・セッションとして起動されたInternet Explorer、そしてVS.NET版のMSDNを表示しているHTML Helpのウィンドウなどを合わせて、メモリを256Mbytes近く消費している。メモリ128Mbytesのマシンで何とかなる世界ではない。急遽メモリ増設を行って256Mbytesとしたところ、納得できる範囲内の時間で、デバッグ・セッションに入れるようになった。

 WebFormは、基本的にHTMLとソース・コード(C#など)の2本立てで構成される。言うまでもなく、HTMLはクライアント側に送信されるもので、C#ソースはサーバ側で自動的にコンパイルされ、実行される。両者は一体不可分で協調して動作するものである。もともと、Webサーバ上にプロジェクトが生成されるため、一体不可分の関係も自動的に作り込まれる。変な設定変更を行わなければ、問題ないだろう。

 HTMLの編集は、これまでのよくあるMicrosoft製のHTMLツールのように、デザイン・モードとHTMLソースモードが存在する。デザイン・モードでは、すべてのコンポーネントが上から下に向かって配置されるモードと、すべてのコンポーネントが絶対座標で配置できるモードが選べる。後者を使うとVBライクに作業ができるが、Webブラウザ経由で操作されることを考えると、安易に絶対座標でコントロールを配置して、結果として横スクロールしないと使えないページになったりすると使い勝手が悪くなる。目的にもよるが、特に理由がなければ、絶対座標は使わない方がベターと言えるだろう。

 さて、ツール・ボックスからボタンをダブルクリックすると、フォーム上のカーソル位置にボタンが追加される。HTMLソースに挿入されるのは、もちろん、普通のHTMLタグであって、特殊なオブジェクトへの参照が埋め込まれるわけではない。C#ソースの方を見ると、WinFormのときと同じように、メンバ変数としてボタンに対応するオブジェクトが生成されている。そして、フォーム上のボタンをダブルクリックすると、C#ソースに、ボタンを押したときに実行されるイベント・ハンドラが追加される。この部分は、まるでVBと同じ挙動だ。

 それではと、テキスト・ボックスとボタンをフォーム上に貼り込んで、ボタンのイベント・ハンドラに、VB感覚で、

Text1.Text = "clicked!";

と書いたら、何が起こるのだろうと思って試してみた。

WebForm上へのコントロールの配置

WebFormでは、あたかもVBのような感覚で、ボタンなどのコントロールをWebページ上に配置し、それらが操作された際の処理をイベント・ハンドラとして記述することができる。作成したプログラム・コードはWebサーバ側で実行され、クライアト側のWebブラウザには、その結果として通常のHTMLデータが送信されるので、クライアント側には標準的なWebブラウザさえあればよい。
  WebForm上に配置されたコントロール。ツール・ボックスから挿入したいコントロールのボタンをダブルクリックすると、それがフォーム上のカーソル位置に追加される。
 

コントロールに対するコードをVB感覚で追加した

フォーム上にコントロールを配置すると、WinFormのときと同様に、コントロールに対応するオブジェクトがメンバ変数として生成される。そしてフォーム上のコントロールをマウスでダブルクリックすると、ボタンを押したときに実行されるイベント・ハンドラがC#のソース・コードに追加される。後はVBと同じように、このイベント・ハンドラの内部で、コントロールが操作された際のプログラムを記述すればよい。
  フォーム上に配置したプッシュ・ボタンのイベント・ハンドラ。ボタンがクリックされると、このハンドラが呼び出される。ここでは例として、ボタンがクリックされたら、ボタンの左に配置したテキスト・ボックスに“clicked”という文字列を表示するための1行のコードを挿入してみた。

 すると、まさに、VBで期待されるとおりの動作をしてくれた。つまり、ボタンを押すとテキスト・ボックスの中に“clicked”という文字列が入ったのだ。

 調子に乗っていろいろ試してみたが、VBと違って、クライアント・サーバ間で通信しながら動作しているので、あまり細かい動作はイベントとして捕まえられないことが分かった。たとえば、リストボックスで選択位置を変えた、というようなイベントは用意されていない。このあたりは、従来のVBと比較すると機能低下にあたるわけで、完全な代用品にはならない。だが、VB感覚でフォームを作っていくだけで、ネットワークで分散して処理されるアプリケーション・ソフトが作成できると言うのは、かなり大きなインパクトだ。しかも、基本的にWebブラウザは特定のソフトである必要がない。どんな端末機器からアクセスしても機能するソフトウェアを、VB感覚でこんなにも手軽に作れると言うのは、インパクトが大きい。

 それならばこれはどうだ、とイベント・ハンドラにブレークポイントを仕掛けて、実行してみた。Webブラウザ上からボタンを押すと、見事にブレークポイントで停止した。デバッグもきちんと機能しているようだ。

動的にページを組み立てる方法

 最初、既存のコンポーネントを配置する方法はすぐ分かったのだが、自分で思いどおりのHTML文を送信する方法が分からなかった。だがサンプルを調べて、動的にページを組み立てる方法が分かった。要するに、WebForm用のコントロールを持つオブジェクトを動的に生成して、これをページのコントロール・コレクションに追加してやればよいのだ。逆に言えば、ページが持っているコントロールのコレクションを好き勝手に操作すれば、ページ内容は自由自在に変化するということを意味する。もちろん、コレクションをいじるということは、実際には、Webブラウザに送信されるHTML文書の内容が変化すると言うことである。しかし、そのあたりの構造は、すべてカプセル化されて隠されているため、意識する必要はない。そのようなことは忘れて、WebFormのコントロールを変化させるコードに専念すれば、自動的にそれに追従して送信されるHTMLも変化するわけだ。これは、1つのソフトウェアを開発している間に、プログラム言語を考える頭と、HTMLを考える頭を切り換える必要がないという意味で、ストレスを軽減してくれると考えられる。また、処理ロジックと、それを生成するコードが、1つのC#ソース上に乗るため、プログラムの見通しがよくなることが期待できる。


 INDEX
  [特集]C#/Visual Stduio.NET/.NET Frameworkの実像を探る
    1.Visual Studio.NETのIDE ―― 意外にもVisual J++のIDEの直系子孫 ――
  2.何はともあれ、C#プログラミングを体験しよう
    3. まとめと前回記事への補遺


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

本日 月間