コンポーネントの初期化と終了
コンポーネントはコンストラクター (Visual Basic のSubNew ) によって初期化され、デストラクター (Visual Basic のSubFinalize) によって破棄されます。コンポーネントのコンストラクターは、コンポーネントのインスタンス作成時に呼び出されます。それより後に呼び出されることはありません。デストラクターは、ガベージ コレクションによりコンポーネントが破棄されてメモリがクリアされる直前に呼び出されます。
Visual Basic メモ |
---|
Visual Basic の以前のバージョンでは、Initialize イベントと Terminate イベントがコンストラクターとデストラクターの役割を果たしていました。 |
ガベージ コレクション待ち
実行中のいずれのコードからもコンポーネントが呼び出されないとガベージ コレクションが判定した場合、共通言語ランタイムはコンポーネントのデストラクターを呼び出します。これは、当該コンポーネントへの参照がすべて解放されている場合に起こります。また、実行中のコードから完全に独立したオブジェクトだけが当該コンポーネントを参照している場合 (循環参照の場合など) にも起こります。
ユーザーがコンポーネントの使用を終えてからデストラクターが呼び出されるまでには時間差が生じ得るため、.NET Framework コンポーネントの有効期間に処理手順を追加する必要があります。コンポーネントがデータベースとの接続や Windows のシステム オブジェクトを識別するハンドルなどのシステム リソースを取得する場合は、IDisposable インターフェイスを実装してください。また、コンポーネントのユーザーがリソースの解放タイミングを指定するための Dispose メソッドを用意してください。
コンポーネントの有効期間
型の初期化: コンポーネントの最初のインスタンスを作成した場合は、実行される最初のコードが共有初期化コードです。共有メンバーへの参照を行っても共有コンストラクターが実行されます。初期化されるすべての共有フィールド (メンバー変数) および、もしあれば、共有コンストラクター (SharedSubNew) もこれに含まれます。クラス全体の参照フォントを作成するコードを次に示します。
[!メモ]
Shared に相当する C# のキーワードは、static です。Visual Basic の Static キーワードと混同しないでください。
Public Class ADrawing
Shared ReadOnly ReferenceFont As New Font("TimesNewRoman", 14)
' Shared constructor does not overload other constructors.
Shared Sub New()
' There is no call to the base class's shared constructor.
' Insert code to initialize the shared data.
End Sub
End Class
class ADrawing
{
static Font m_referenceFont = new Font("TimesNewRoman", 14);
// Simply add the static keyword to create a static constructor.
// Static constructors do not have any parameters.
static ADrawing()
{
// There is no call to the base class's static constructor.
// Code to initialize the font here.
}
}
[!メモ]
クラスの初期化は、コンポーネントのインスタンスが作成されていない場合でも発生することがあります。たとえば、共有メンバー関数を含む abstract (MustInherit) クラスは、そのクラスのインスタンスが作成されていなくても初期化され、それらの関数をアプリケーションで使用することができます。
インスタンスの初期化: コンポーネントのインスタンスの作成時に、初期化コードを持つデータ メンバーが初期化され、適切なコンストラクターのオーバーロードが実行されます。次のコードでは、プライベート フィールドを初期化し、2 つのコンストラクターを定義しています。一方はパラメーターがない場合に呼び出され、もう一方はユーザーがパラメーターを指定した場合に呼び出されます。
Class AShape Private answer As Integer = 42 Public Sub New() ' Call another constructor with default initialization values. MyClass.New(System.Drawing.Color.Red, 5280, DefinedSizes.Large) End Sub Public Overloads Sub New(myColor As Color, myLength As Integer, _ Size As DefinedSizes) ' Insert code to initialize the class. End Sub ' Defines the DefinedSizes enum Public Enum DefinedSizes Large Small End Enum End Class
class AShape { private int m_answer = 42; // Forward to another constructor. public AShape() : this(System.Drawing.Color.Red, 5280, DefinedSizes.Large) { // Additional initialization goes here. } public AShape(Color color, int length, DefinedSizes size) { // Code to initialize the class goes here. } // Defines the DefinedSizes enum public enum DefinedSizes { Large, Small } }
リソースの破棄: コンポーネントに IDisposable インターフェイスを実装する場合は、コンポーネントの使用が終了したときにクライアントで呼び出す Dispose メソッドを用意する必要があります。Component を継承するコンポーネントには、既定の Dispose が既に実装されています。この実装をオーバーライドして、クリーンアップ コードを追加することができます。コンポーネントの Dispose メソッドでは、割り当てられた可能性があるすべてのシステム リソースを解放し、他のオブジェクトへの参照を解放し、そのコンポーネント自体を使用できなくします。コンポーネントによっては、独自の Dispose メソッドを呼び出した方が適している場合もあります。次のコードでは、Dispose メソッドを持つ依存オブジェクトを破棄しています。
' Assumes that the class implements IDisposable Public Sub Dispose() Implements IDisposable.Dispose myWidget.Dispose myWidget = Nothing ' Insert additional code. End Sub
// Assumes that the class implements IDisposable public void IDisposable.Dispose() { mywidget.Dispose(); mywidget = null; // Dispose of remaining objects. }
Dispose を呼び出した後、クライアントで、コンポーネントへの参照が残っている場合はすべて解放し、ガベージ コレクションでコンポーネントのメモリをクリアできるようにする必要があります。
Instance destruction: コンポーネントへの参照が残っていないことをガベージ コレクションが検出されると、ランタイムはコンポーネントのデストラクター (Visual Basic のFinalize) を呼び出してメモリを解放します。独自のクリーンアップ コードを実装するには、基本クラスの Finalize メソッドをオーバーライドする (Visual Basic の場合) か、デストラクターを実装する (Visual C# の場合) 必要がありますが、デストラクターまたは基本クラスの Finalize メソッドの呼び出しは必ず含めてください。
Protected Overrides Sub Finalize() m_Gadget = Nothing m_Gear = Nothing MyBase.Finalize() End Sub
// In C#, a destructor is used instead of a Finalize method. ~ThisClass() { m_gadget = null; m_gear = null; // The base class finalizer is called automatically }
メソッドを実装するタイミング
Component から継承するコンポーネントの場合は、Dispose の実装が既定で用意されています。この実装をオーバーライドして、独自のクリーン アップ コードを提供できます。IComponent の実装を独自に作成してコンポーネントをビルドする場合は、IDisposable を実装してコンポーネントに Dispose メソッドを用意してください。
システム オブジェクト、データベース接続、またはユーザーが使用を終えたらすぐに解放する必要のある希少なリソースを割り当てるコンポーネントには、Dispose メソッドが必要です。
Dispose メソッドを持つ他のオブジェクトへの参照があるコンポーネントにも、Dispose メソッドを実装する必要があります。
Dispose の実装理由
システムの利用状況によっては、ユーザーがコンポーネントの使用を終えてから、コンポーネントのコードに到達できないことをガベージ コレクションが検出するまで、予測できない間隔が空くことがあります。Dispose メソッドを用意しないと、コンポーネントはこの間中、リソースを保持し続けます。
最悪の事態
データベース接続を使用し、Dispose メソッドを持たないサーバー コンポーネントを想像してください。大量のメモリを搭載するサーバーでは、空きメモリに大きな影響を与えずにコンポーネントのインスタンスを多数作成して解放することもできます。この場合、コンポーネントへの参照が解放されてからしばらくの間は、ガベージ コレクションではコンポーネントが破棄されないことがあります。
その結果、使用できるデータベース接続のすべてが、解放済みで破棄されていないコンポーネントに使用されたままになってしまうこともあります。そのため、サーバーのメモリが不足していなくても、ユーザーの要求に応じられなくなる可能性があります。
参照
処理手順
方法 : デザイン モードでコンポーネントを作成および設定する