連載

C#入門

第11 コンストラクタとデストラクタ

(株)ピーデー
川俣 晶
2001/09/13


コンストラクタとは何か?

 すでに説明したとおり、C#はクラスを記述する能力があり、クラスからインスタンスを生成することができる。今回説明するコンストラクタとデストラクタは、インスタンスの生成・消滅と密接に関係する機能である。まずはコンストラクタから説明しよう。

 クラス内に変数などがある場合、インスタンスを生成してから変数を利用するまでの間に、適切な値を初期値として設定したい場合がある。また、入出力機器を扱うクラスなら、入出力ハンドルを初期化したいと思うこともあるだろう。そのような場合に対応するために、C#にはコンストラクタという機能がある。コンストラクタは、インスタンスが生成された瞬間に実行されるメソッドの一種である。このメソッドに、インスタンス生成時に実行させたいコードを書いておけば、自動的に生成時に呼び出され、実行される。

 もっとも簡単なコンストラクタの例を以下に示す。

 1: using System;
 2:
 3: namespace ConsoleApplication36
 4: {
 5:   class Class2
 6:   {
 7:     public Class2()
 8:     {
 9:       Console.WriteLine("public Class2()");
10:     }
11:   }
12:   class Class3
13:   {
14:     public Class3( int x, int y )
15:     {
16:       Console.WriteLine("public Class3({0},{1})",x,y);
17:     }
18:   }
19:   class Class1
20:   {
21:     static void Main(string[] args)
22:     {
23:       Class2 t1 = new Class2();
24:       Class3 t2 = new Class3( 1, 2 );
25:     }
26:   }
27: }
コンストラクタを記述したサンプル・プログラム1

 さて、7〜10行目がClass2クラスのコンストラクタである。7行目を見て分かるとおり、コンストラクタの名前は、クラス名と一致させねばならない。また、コンストラクタは暗黙のうちに実行されるため、戻り値は存在しない。そのため、戻り値のデータ型は書かない。事実上voidに相当するが、voidとは書かない。

 このコンストラクタは、どこからも呼び出されていないが、23行目でClass2クラスのインスタンスがnewによって生成された時点で自動的に呼び出されている。

 さて、コンストラクタに戻り値はないが、引数を付けることはできる。引数のあるコンストラクタの事例が14〜17行目のClass3クラスのコンストラクタである。ここでは、整数型のxとyという引数を持っている。このコンストラクタを呼び出す場合は、24行目のように、newでクラス名を記述した後に引数のリストを記述する。newがコンストラクタを必ず呼び出すのは明らかなので、newに書いた引数は確実にコンストラクタに届く。

 これを実行した結果は以下のようになる。明示的には呼び出されていないコンストラクタが呼び出されている様子が分かると思う。

サンプル・プログラム1の実行結果
コンストラクタはnewによりインスタンスを生成した時点で暗黙的に呼び出される。戻り値は持たない。

コンストラクタのオーバーロード

 C#には、1つのクラスに引数の異なる同名のメソッドを扱う機能がある。これをオーバーロードという。コンストラクタもオーバーロード可能なので、引数の異なる複数のコンストラクタを1つのクラスに持たせることができる。以下はその例である。

 1: using System;
 2:
 3: namespace ConsoleApplication29
 4: {
 5:   class Class2
 6:   {
 7:     public Class2()
 8:     {
 9:       Console.WriteLine("public Class2() called");
10:     }
11:     public Class2( int x )
12:     {
13:       Console.WriteLine("public Class2( int x ) called");
14:     }
15:     public Class2( string s )
16:     {
17:       Console.WriteLine("public Class2( string s ) called");
18:     }
19:   }
20:   class Class1
21:   {
22:     static void Main(string[] args)
23:     {
24:       Console.WriteLine("new Class2();");
25:       Class2 t1 = new Class2();
26:       Console.WriteLine("new Class2( 1 );");
27:       Class2 t2 = new Class2( 1 );
28:       Console.WriteLine("new Class2(( \"Hello!\" );");
29:       Class2 t3 = new Class2( "Hello!" );
30:     }
31:   }
32: }
コンストラクタのオーバーロードを使用したサンプル・プログラム2

 7〜10行目は引数のないコンストラクタ。11〜14行目は引数として1つの整数を取るコンストラクタ。15〜18行目は引数として1つの文字列を取るコンストラクタである。

 これを実行した結果は以下のようになる。

サンプル・プログラム2の実行結果
同じクラスであっても、newに与える引数に従って異なるコンストラクタを呼び出すことができる。

 実行結果を見れば分かるとおり、1回のnewで実行されるコンストラクタは1つきりである。コンストラクタが複数存在していても、実行されるのは、その中の1個だけである。

複数コンストラクタの実行

 今見たとおり、複数のコンストラクタがあっても、実行されるのは1つきりである。しかし、共通の初期化コードなどがあった場合、このような仕様は不便である。1個のコンストラクタの処理を行うとき、別のコンストラクタも呼べれば、ずっとプログラムがすっきりする。そこで、明示的に同じクラス内にある別のコンストラクタを呼び出す構文がC#にはある。具体的には、以下のサンプルソースのように記述する。

 1: using System;
 2:
 3: namespace ConsoleApplication30
 4: {
 5:   class Class2
 6:   {
 7:     public Class2()
 8:     {
 9:       Console.WriteLine("public Class2() called");
10:     }
11:     public Class2( int x ) : this()
12:     {
13:       Console.WriteLine("public Class2( int x ) called");
14:     }
15:     public Class2( string s ) : this(1)
16:     {
17:       Console.WriteLine("public Class2( string s ) called");
18:     }
19:   }
20:   class Class1
21:   {
22:     static void Main(string[] args)
23:     {
24:       Console.WriteLine("new Class2();");
25:       Class2 t1 = new Class2();
26:       Console.WriteLine("new Class2( 1 );");
27:       Class2 t2 = new Class2( 1 );
28:       Console.WriteLine("new Class2( \"Hello!\" );");
29:       Class2 t3 = new Class2( "Hello!" );
30:     }
31:   }
32: }
“: this(…)”により、別のコンストラクタを呼び出すコンストラクタを使用したサンプル・プログラム3

 まず11行目に注目していただきたい。11行目には、前のサンプルにない“:this()”という文字列が付加されている。これは、このコンストラクタの実行に先立って、同じクラス内で、引数なしのコンストラクタを実行せよ、という意味を持つ。つまり、7〜10行目のコンストラクタ(引数指定なしのときに呼び出されるコンストラクタ)が、11〜14行目のコンストラクタの実行に先立って実行されるように指示している。

 “:this()”のカッコ内には引数を記述することができる。15行目が引数を記述した例である。引数に1という数字を記述しているが、これはint型である。int型を1個引数に取るコンストラクタといえば、11〜14行目のコンストラクタであるから、このコンストラクタが呼び出されることになる。

 これを実行した結果は以下のようになる。

サンプル・プログラム3の実行結果
あるコンストラクタから別のコンストラクタを呼び出すことができるため、共通した初期化処理などをまとめて記述することができる。実行されるコンストラクタの順番には注意が必要だ。

 ここで注意してほしいのは、コンストラクタが実行される順番である。例えば“new Class2( "Hello!" );”で実行されるコンストラクタは“public Class2( string s ) : this(1)”である。しかし、このコンストラクタを実行する前に“: this(1)”によって、“public Class2( int x ) : this()”が実行される。しかし、これを実行する前に、“: this()”の効能により、“public Class2()”が実行される。その結果、直接指定したコンストラクタが実行されるのは最後にまわされる。

 

 INDEX
  第11回 コンストラクタとデストラクタ
  1.コンストラクタとは何か?
    2.baseクラスのコンストラクタの呼び出し
    3.デストラクタとは何か?

「C#入門」


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

本日 月間