フレッシュマン企画 連載
|
|
|
■Windowsフォーム・デザイナで生成されたコード(Form1.Designer.cs)
次のコードはForm1.Designer.csファイルの内容である。
|
|
Windowsアプリケーションのフォーム・デザイナ用のコード(Form1.Designer.cs) | |
Form1.Designer.csファイルに部分クラスとして定義されたForm1クラスには、1つのフィールド変数と3つのメソッドがある。なお、InitializeComponentメソッドの前後にある「#region Windows <コメント>」〜「#endregion」の部分は「アウトライン機能」と呼ばれ、コードを折り畳んで非表示にすることが可能な場所である。詳しくは、.NET TIPSの「.NET TIPS:VS.NETでソース・コードを見やすくするには?」を参照していただきたい。 |
Form1.Designer.csファイルに部分クラスとして分離されたForm1クラスには、次のような変数(「フィールド変数」とも呼ばれる)とメソッドがある。
(1) フィールド変数:private System.ComponentModel.Container components
(2) メソッド:protected override void Dispose( bool disposing )
(3) メソッド:private void InitializeComponent()
このように、先ほどのForm1.csファイルのForm1クラスのコンストラクタで呼び出されていたInitializeComponentメソッドは、Form1.Designer.csファイルに部分クラスとして分離されたForm1クラス内にあることが分かった。なお、Form1クラスを正確に宣言すると「public partial class Form1 : System.Windows.Forms.Form」と記述しなければならないわけだが、上記コードを見れば分かるように、部分クラスではアクセス修飾子(この例では「public」)や基底クラス(この例では「: System.Windows.Forms.Form」)は省略可能だ*3。
*3 部分クラスとして分離されたクラスのどれか1つにアクセス修飾子と基底クラスの宣言が含まれていれば、そのほかのクラスではこれらを省略できる。本稿で説明するWindowsアプリケーションのひな型コードの例では、Form1.csファイルのForm1クラスの方にアクセス修飾子と基底クラスが宣言されているので、Form1.Designer.csファイルのForm1クラスでは省略可能となる。 |
それでは、これらのフィールド変数やメソッドについて、個別に解説していこう。
●(1)のcomponents変数
(1)の「components」変数はクラス内で使用されるフィールド変数で、コンポーネントを管理するためのものだ(「コンテナ」と呼ばれる)。コンポーネントについては、改訂版 C#入門の「Column - コンポーネントとコントロール -」を参照してほしい。
private System.ComponentModel.Container components = null;
ここではcomponents変数に「null」が代入されているが、(3)で説明するInitializeComponentメソッドの中に、次のようなコードが自動的に生成されるため、ほぼ初期状態のContainerオブジェクト(System.ComponentModel名前空間)がcomponents変数に格納されることになる。
this.components = new System.ComponentModel.Container();
このcomponents変数は、次に説明する「(2)のDisposeメソッドで終了処理」で使用される。
●(2)のDisposeメソッドで終了処理
(2)の「protected override void Dispose( bool disposing )」では、終了処理(=後処理。不要なデータを破棄する処理やクラス終了時に実行しなければならない処理)を記述する。ここでは、初期化処理はコンストラクタ、終了処理はDisposeメソッドで行うと、対にして覚えておけばよい(終了処理については下のコラムを参照)。
【コラム:ファイナライザ(=デストラクタ)について】 なお、暗黙的に終了処理を行うためには(つまり、ガベージ・コレクション機能に自動的に後処理を行わせるには)、Disposeメソッドではなくファイナライザを実装することになる。ファイナライザを実装するには、コンストラクタ名の先頭にチルダ(~)を挿入したメソッド名で「~Form1()」と記述するだけだ(VBでは「Overrides Protected Sub Finalize()」というメソッド名になる)。終了処理についてさらに詳しくは「.NET TIPS:確実な終了処理を行うには?」を参照するとよい。 |
Disposeメソッドでは、protected修飾子の次に、さらにoverride修飾子がある。C#のoverride修飾子(VBでは Overrides修飾子)は、継承されたクラスでのみ使用できる修飾子で、基底クラスにあるメソッドを新しい派生クラスのメソッドで置き換えることを示すためのものだ。
つまり、このひな型コードでは、「基底クラスであるFormクラス(System.Windows.Forms名前空間)のDisposeメソッドを、派生クラスであるForm1クラス(WindowsApplication1名前空間)のDisposeメソッドで置き換える」ということを示している。このようなメソッドの置き換えを、オブジェクト指向言語では、メソッドの「オーバーライド」と呼ぶ。
Disposeメソッドの実装内容は次のようになっている。
protected override void Dispose( bool disposing )
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
まず「if (<bool値>)」というコードはそのまま英語の意味で、「もしbool値(=trueとfalseという2種類の値のみを入れられる)がtrueなら、続く { …… } のスコープのコードを実行する」という意味である。「&&」演算子は論理積を表し、日本語で表現するなら「かつ」という語句に当てはまる。すなわち「A && B」は「AかつB」という意味になる。まとめると、上記コードの「if (disposing && (components != null))」は、「もしdisposingがtrueで、かつ、(components != null)がtrueなら、続く { …… } のスコープのコードを実行する」という処理コードになる。
まず「disposing」はDisposeメソッドのパラメータに指定されたbool型の変数(=bool値)である*4。次に「(components != null)」というコードだが、C#の「!=」比較演算子は「同じではない」を表すので(ちなみに「==」が「同じである」を表す)、このコードの意味は「componentsがnullと同じではない」となる。前述のとおり、components変数には(3)のInitializeComponentメソッドでContainerオブジェクトが代入されるので、「componentsがnullと同じではない」は「正しい(=true)」という結果になる。従って、「disposing」がtrue、かつ、「(components != null)」がtrueなので、「if (disposing && (components != null))」の次にある { …… } のスコープのコードが実行されることになる。
*4 このDisposeメソッドのdisposingパラメータは、Disposeメソッドがユーザーのコードによって直接もしくは間接的に呼び出されたときにtrueとなり、共通言語ランタイム(=.NET実行エンジン)のファイナライザによって呼び出されたときにはfalseとなる。本稿で説明しているForm1クラスのように、Application.Runメソッドから実行されたクラスのDisposeメソッドの場合には、Runメソッドの内部コードから間接的にDisposeメソッドが呼ばれるため、disposingパラメータの値はtrueとなり、{ …… } のスコープのコードが実行されることになる。 |
そのスコープ内には「components.Dispose();」というコードがあるが、これはcomponents変数の終了処理を行うために、さらにcomponents変数のDisposeメソッドを呼び出すコードである*5。
*5 Windowsフォーム・デザイナでコンポーネントを追加すると、コンテナであるcomponents変数にそのコンポーネントが登録される。そこで登録されたすべてのコンポーネントのDisposeメソッドは、ここのcomponents変数のDisposeメソッドの中から呼び出されるため、すべてのコンポーネントのリソース破棄などの後処理を漏れなく実行できるという仕組みになっている。 |
最後にある「base.Dispose( disposing );」は、基底クラスのDisposeメソッドを呼び出すコードである。前回の継承の説明でも述べたようにForm1クラスには、継承元となる基底クラスが存在する。その基底クラスのオブジェクトは「base」というキーワードにより参照できる(VBでは、「MyBase」というキーワード)。このキーワードは通常のオブジェクトのように「オブジェクト名.メソッド名」の形式で利用することができる。よって、この「base.Dispose( disposing );」というコードは、「基底クラスにあるDisposeメソッドを呼び出す」という処理コードになる。
●(3)のInitializeComponentメソッドで“実際の”初期化処理
(3)の「private void InitializeComponent()」は、Form1.csに記述されたForm1クラスのコンストラクタから呼び出されるクラス内部専用(=private修飾子)のメソッドである。InitializeComponentメソッドの内容を見ると、次のようになっている。
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "Form1";
}
メソッドの中の最初の1行目は、前述の「(1)のcomponents変数」で説明した。
2行目の「this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;」は、Windowsフォームやその中のコントロールのサイズを自動調整(=自動スケーリング)する際の基準を示すモードを指定する。代表的なモードには以下のものがある。この表を見ると、ここではフォント・サイズを基準にした自動スケーリングを行うモードを指定していることが分かる。
モードの種類 | 自動スケーリングの基準 |
System.Windows.Forms.AutoScaleMode.Dpi | ディスプレイ解像度 |
System.Windows.Forms.AutoScaleMode.Font | フォント・サイズ |
自動スケーリングの基準を示すモード |
3行目の「this.Text = "Form1";」は、Windowsフォームのタイトル・テキストを指定するためのコードで、ここでは「Form1」を指定している。この値を変更するには、前々回説明したWindowsフォーム・デザイナ画面で、[プロパティ]ウィンドウの[Text]プロパティを書き換えればよい。
以上のようにInitializeComponentメソッド内では、Form1オブジェクト(=Windowsフォーム画面)の初期値を設定している。
INDEX | ||
[フレッシュマン企画 連載]簡単!Visual Studio 2005入門 | ||
第4回 Visual Studio 2005のひな型コードを理解する | ||
1.Mainメソッドの内容の理解 | ||
2.Application.Runメソッドの理解 | ||
3.Windowsフォーム・デザイナで生成されたコード | ||
4.ひな型コード全体の流れ | ||
「簡単!Visual Studio 2005入門」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|