ラベル デストラクタ の投稿を表示しています。 すべての投稿を表示
ラベル デストラクタ の投稿を表示しています。 すべての投稿を表示

2018年2月21日水曜日

C#におけるコンストラクタとデストラクタの話

リストを入力して動かしてみる、という学習はまだまだ続きます。

コンストラクタ


今回はコンストラクタの話です。どうでも良い話ですが、最近はコンストラクターと長音(ー)を入れる書き方が普通なんでしょうか。僕は工学者出身なので、後ろの長音は省略する習慣が抜けません。

オブジェクトを生成する、つまりクラスのインスタンスを生成する際には、オブジェクトをキチンと初期化してあげなければいけません。そのために、new演算子でインスタンスを生成するときにだけ走る、特別なメソッドが用意されています。これをコンストラクタといいます。

コンストラクタは、クラスの名前と同じ名前で定義し、戻り値の型は書きません。コンストラクタは戻り値を持つことが許されません。コンストラクタの働きを考えると、戻り値を持つ意味がありませんね。

学習の際に打ち込んだリストは以下です。

/*
 * コンストラクターの学習
 */
using System;

namespace sample9
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person("gustav", 123);
            p.print();
            Console.ReadKey();
        }
    }

    public class Person
    {
        public string name;
        public int age;
        public Person( String name, int age ) ←これがコンストラクタ
        {
            this.name = name;
            this.age = age;
        }

        public void print()
        {
            Console.WriteLine("My name is " + name + ". I'm " + age + " old.");
        }
    }
}

Personクラスの中の、

public Person( String name, int age )

がコンストラクタになります。このプログラムでは引数をクラスのメンバーである変数nameとageに代入しています。これを実行した結果が以下です。1行目でコンパイル、2行目で実行、3行目が出力結果です。

MacBook-Pro:sample9 gustav$ mcs Program.cs
MacBook-Pro:sample9 gustav$ mono Program.exe
My name is gustav. I'm 123 old.

コンストラクタは、オーバーライドすることができます。

/*
 * コンストラクターの学習2
 */
using System;

namespace sample9
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person("gustav", 123);
            Person p2 = new Person();
            
            p.print();
            p2.print();
            Console.ReadKey();
        }
    }

    public class Person
    {
        public string name;
        public int age;
        public Person( String name, int age )
        {
            this.name = name;
            this.age = age;
        }

        public Person()
        {
            this.name = "{NONAME}";
            this.age = 1;
        }

        public void print()
        {
            Console.WriteLine("My name is " + name + ". I'm " + age + " old.");
        }
    }
}

Personクラスの中で、引数が二つある場合と引数がない場合のコンストラクタを定義しています。インスタンス生成で引数を与えたインスタンスと引数を与えなかったインスタンスで、それぞれ異なった初期値がメンバー変数に与えられていることがわかります。

MacBook-Pro:sample9-2 gustav$ mcs Program.cs
MacBook-Pro:sample9-2 gustav$ mono Program.exe
My name is gustav. I'm 123 old.
My name is {NONAME}. I'm 1 old.

デストラクタ


インスタンス生成で生成されたオブジェクトを初期化するためのメソッドがコンストラクタでしたが、オブジェクトが破棄されるときに呼び出されるメソッドというものもあります。それがデストラクタです。

メソッド名を、~クラス名として定義、引数は持てない、ということになっています。上の例に習うと、

~Person()

のような書き方です。

コンストラクタ、デストラクタとも、元々C++にある機能で、コンストラクタはC++と同じ考え方で扱えば良いのですが、C#のデストラクタは、C++のデストラクタとは少々勝手が違います。

C++では、クラスをdeleteした時点、もしくはクラスのスコープを抜けた時点でデストラクタが呼び出されますが、C#ではオブジェクトの寿命をプログラムで制御することが出来ず、ガベージコレクターがオブジェクトを破棄したときに初めてデストラクタが呼び出されます。

ということで、プログラムからの制御が出来ないということは、プログラムを書く側からするととても使いにくい、ということになるので、C#ではデストラクタはあまり使われないようです。

参考文献:++C++ ; // 未確認飛行C コンストラクターとデストラクター

今回はここまでです。