第3回 .NETのコードを理解するための基礎知識:連載:簡単! Visual Studio 2017入門(3/3 ページ)
.NETによるWindowsアプリケーションのコードを理解するために必要な知識とは? まずはプログラミングの基礎を身に付けよう。
クラスのインスタンスが生成されるきっかけとなる「エントリポイント」
以上で、ひな型コードには、WindowsFormsApp1名前空間のForm1クラスという要素があることが分かった。このForm1クラスは第1回で実行した.NETプログラムのウィンドウの「元の姿」である。つまりソースコードは、実体そのもの(=ウィンドウ)ではなく、実体を構築するための設計図(=元の姿)でしかない。
例えば現実世界では、DNAという設計図に基づいて実体(=人間)が生まれる。それと同じように、プログラミングの世界でも、クラスのコードという設計図に基づいて実体(=インスタンス)が生成されるのである(なお、「クラスのインスタンス」として生成されたものが「オブジェクト」なので、ここで覚えておいてほしい)。
現実世界の人間を最初に創造したのは誰か分からないが、ここでは便宜上「創造者」としておこう。プログラミング(C#、VB)の世界では、この創造者が誰かということは、はっきりしている。クラスという設計図からオブジェクトを作り出す創造者は、Windowsシステム(厳密には.NET Frameworkの実行エンジン)である。
しかし、Windowsシステムが全てのオブジェクトを作り出すわけではない。ただ単に、そのきっかけを作っているだけである。きっかけが作られた後は、あるオブジェクトが次々に新しいオブジェクトを作成していき、最終的にそれらのオブジェクト同士の結び付きややりとりによってプログラム全体が実行されることになる。これは現実世界で、人間が人間を生んでいき、最終的にそれらの人間同士の結び付きとやりとりによって社会全体が回っていくことに似ている。
プログラミングの世界では、これらのオブジェクトが生誕する最初のきっかけとなる場所は、「エントリポイント」と呼ばれる。
アプリのメインエントリポイント「Mainメソッド」
C#ではWindowsフォームアプリやコンソールアプリのエントリポイントは「Mainメソッド」である(メソッドについては後述)。そのため、プログラム内に最低1つのMainメソッドが必要となる(なおVBでは、このMainメソッドを省略できるが、その際には暗黙的にプログラム内にMainメソッドが作成される)。
次のコードを見ると、確かにソースファイルの中にMainメソッドがあるのが確認できる。MainメソッドがあるのはProgram.csファイルである。
……前略……
namespace WindowsFormsApp1
{
static class Program
{
……中略……
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
……中略……
}
}
}
アプリには1つ以上のエントリポイントが必要である。
Mainメソッドについて解説する前に、Programクラスと「///」で始まる行の意味について簡単に触れておこう。
まずProgramクラスは次のように記述されている。
static class Program
{
……中略……
}
このコードではまずアクセシビリティが省略されている。前述したように省略すると、自動的にinternal修飾子が付与されるため、「internal static class Program」と記述したのと等価になる。
次に「static」という修飾子が付けられている。static修飾子を付けたクラスは「静的クラス」と呼ばれ、先ほど説明したクラスのインスタンス化が不要になる(※ちなみにVBには静的クラスという機能はないが、それに近いモジュール(Module)という機能が用意されている)。静的クラスは、プログラムを実行すると、.NETの実行エンジンによって自動的に読み込まれるので、インスタンス化することなく、そのクラス内のメソッドが使えるようになる。
またC#では、次のコードのように「//」や「///」(VBでは「'」)が記述されている行は「コメント」と呼ばれ、「//」から、その行の行末までの部分は最終的に生成されるプログラムには含まれない。
/// アプリケーションのメイン エントリ ポイントです。
「//」(VBの場合は「'」)から行末までに書かれた内容はプログラムの動作には影響を及ぼさない。
コメントを使えば、プログラムの内容説明や注意書きをソースコードの中に記述できる。また、既存のコードの先頭部分に「//」を記述すれば、そのコードをコメント化、つまりプログラムに含まれないようにできる(「コメントアウト」と呼ばれる)。プログラムの開発途中で特定の行を抜かして(あるいは書き換えて)プログラムを実行して、その場合のプログラムの挙動を確認したいけれども、その行(あるいは書き換え前の行)は取りあえず残しておきたいといった場合に、その行をコメントアウトしてからプログラムをコンパイル&実行して、その挙動を確認した後でコメントアウトした行を元に戻す(あるいは書き換えた行を採用する)といった使い方をする。
上記コードのコメントの中にある「<summary>」や「</summary>」はコードコメントと呼ばれ、ソースコードからAPIリファレンスを作成するためのものだ(詳細は「特集:ツールを使ったドキュメント作成技法(前編) ― 価値のある開発ドキュメントを効率的に作成するには?」を参照してほしい)。
Mainメソッドの書き方
少し脱線したが、Mainメソッドに話題を戻す。上記のコードを見れば分かるように、C#でのMainメソッドの書き方は、次の通りだ。
[STAThread]
static void Main()
{
……中略……
}
これは「STAThread属性を持つ静的なメソッドMainであり、戻り値はない」と読める(詳細後述)。
まず「[STAThread]」という記述は、.NET以前からのマイクロソフトテクノロジーであるCOM(Component Object Model)のための設定である。メソッドの前に、[ …… ](角かっこ)で記述されるコードは「属性」と呼ばれる.NET言語特有の機能である(詳しくは、改訂版C#入門の「実行時に参照可能な属性」、もしくはプロフェッショナルVBプログラミングの「属性」を参照されたい)。
現段階で、このSTAThread属性の意味を正しく理解する必要はないが、MainメソッドにはSTAThread属性が必要なことは覚えておいてほしい(なおVBの場合は、暗黙的にSTAThread属性が設定されるので、必ずしも記述する必要はない)。
次に「static」というキーワードがある。C#では、このstaticキーワード(VBではSharedキーワード)で修飾されたメソッドは静的メソッドと呼ばれ、クラスの実体(つまりオブジェクト)がなくても呼び出すことができる。一方、静的メソッド以外のメソッドを呼び出すためには、必ずそのメソッドが所属するクラスのオブジェクトが必要になる(詳細後述)。実は前述の静的クラスでは、静的メソッドしか作れない仕組みになっている。
Mainメソッドは、オブジェクトを作成するためのきっかけとして呼ばれるもので、それが呼ばれる時点では、オブジェクトが1つも存在していない。よって、オブジェクトなしでメソッドへのアクセスを可能にするstaticキーワード(VBではSharedキーワード)が必要になるのである。
staticキーワードの次に記述されている「void Main()」が実際のMainメソッドである。
続いては、メソッドについて解説を行おう。
メソッドを定義するには?
メソッドとは、簡単にいうと、右から入力を受け取り、左へ出力するための、変換機のようなものだ。現実世界の例でいえば、お金(入力)を受け取り、ジュースを返すための、自動販売機のようなものである。
これをプログラミング世界のメソッドで表すと、次のようになる。
右の入力部分は「パラメーター(引数:ひきすう)」と呼ばれ、メソッドによってその数は変わる。左の出力は「戻り値」と呼ばれ、必ず1個か0個になる*2。戻り値が0個(=何も出力しない)の場合は、C#では「void」と表記すればよい(「なし」という意味。「ボイド」と発音する。VBで「なし」の場合は戻り値を省略する)。メソッドの実際の処理は、先ほどのクラスや名前空間と同じように {……} のスコープ内で行われる。
*2 C# 7では値タプル(ValueTuple)と呼ばれるデータ構造を使うことで、「(<戻り値1>, <戻り値2>) = DoSomeWork(……)」のような、一見すると複数の値をメソッドが返すような記述が可能だ。それでもなお、この場合のDoSomeWorkメソッドの戻り値あくまでも1つのタプルというオブジェクトである。今の例なら、タプルは2つの値をひとまとめにしたものであって、それを「分解」という操作を介して、<戻り値1>と<戻り値2>に個別に代入している。なお、VB 2017では値タプルは利用可能だが、その値を「分解」して個別の変数に代入することはできない(「(<戻り値1>, <戻り値2>) = DoSomeWork (……)」のような記述はできない)。また、2017年5月10日時点では、値タプルを使用するにはNuGetと呼ばれるパッケージ管理ツールを使用して、プロジェクトにSystem.ValueTupleパッケージをインストールする必要がある。値タプルについては「Visual Studio 2017が目指す世界とは?」や「.NET TIPS:foreachループで現在の繰り返し回数を使うには?[C#/VB]」なども参照してほしい。
Windowsアプリのひな型コードのMainメソッドは、「void Main()」となっているので、パラメーターは0個で(=省略されていて)、戻り値は「void」(=なし)である。
次に定義済みのメソッドを使用する方法を簡単に紹介しておこう。
定義済みのメソッドを使用するには?
先ほどの解説では、メソッドを定義する方法を示した。次に定義済みのメソッドを使用する方法を簡単に紹介しておこう。といっても難しくはない。メソッドの使用パターンは、次の図のパターン1のように「処理結果である戻り値を変数に代入するか」、パターン2のように「戻り値を無視するか(=結果は不要で、メソッドの処理だけを実行するか)」の2通りしかない。
プログラミングの世界におけるメソッドの使用方法(C#)
定義済みのメソッドを使用する方法は、「処理結果である戻り値を変数に代入するか」、パターン2のように「戻り値を無視するか(=結果は不要で、メソッドの処理だけを実行するか)」の2通りしかない。
上の図にある変数の型とは、変数の種類(例えば、数値、文字例、Windowsフォーム、ボタンコントロールなどのクラスの種類)のことである。また変数とは、値(=データ)を格納するための領域(=データを格納する箱のようなもの)である。例えば「int num;」と記述した場合、int型(=数値型)のnum変数ということになる。
「=」は代入するという意味なので、パターン1の「変数の型 変数 = DoSomeWork(パラメーター1, パラメーター2……)」は「パラメーター1、パラメーター2に入力を渡してDoSomeWorkメソッドの処理を行わせ、その処理結果を戻り値として受け取って(変数の型の)変数に代入する」という意味になる。
メソッドの最後にある「;(セミコロン)」は、C#でプログラム上の1文(=1ステートメント)を区切るためのキーワードである。つまり、1行に「;」を複数記述すれば、1行内に複数の文を記述できるし、複数行の最後に「;」を1つ記述すれば、複数行に1つの文を記述できる(VBは、基本的に改行により1文を区切るため、通常は1行=1文となる。なお改行の最後に「_」を付加して連結すれば、VBでも複数行にまたがる1文を記述することは可能。さらにVB 2010以降では、改行だけで複数行にまたがる1文を記述できるようになっている*3)。
*3 MSDNの「Visual Basic におけるステートメント」の「複数行にまたがるステートメント」を参照のこと(VS 2013時点のドキュメント)。なお、最新のドキュメント(2017年5月11日時点で英語版)はこちら。
今回はここまでにしよう。オブジェクト指向プログラミングの基礎部分を簡単に説明したが、これについて詳しく解説することは本連載の趣旨から外れるので、「オブジェクト指向プログラミング超入門」などを読んで、次回までによく理解しておいてほしい。次回はMainメソッドの処理内容から、プログラム全体のコード内容までを一通り解説する。お楽しみに。
Copyright© Digital Advantage Corp. All Rights Reserved.