4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[改訂版]継承可能なSingleton基底クラス(VB.Net)

Posted at

元ネタ

継承可能なSingleton基底クラス(VB.Net)

これに関して後輩と話していたところ「型推論効くっすよ、ディクショナリはいらねーしw」と言われ驚愕。提示されたのが下のソース。

[改訂版]基底クラス

AbstractSingletonClass.vb
''' <summary>
''' [改訂版]シングルトン基底クラス
''' </summary>
''' <remarks></remarks>
Public MustInherit Class AbstractSingletonClass(Of T)

    ''' <summary>
    ''' シングルトンインスタンス
    ''' ディクショナリ不要!!
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared _Instance As T = Nothing

    ''' <summary>
    ''' インスタンス生成排他ロックオブジェクト
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared ReadOnly _SyncLockCreateInstance As New Object

    ''' <summary>
    ''' コンストラクタ(Protected)
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub New()

    End Sub

    ''' <summary>
    ''' インスタンス取得
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetInstance() As T

        SyncLock _SyncLockCreateInstance

            'インスタンス生成済みかチェックする
            If _Instance Is Nothing Then
                '無ければ生成する
                _Instance = CType(System.Activator.CreateInstance(GetType(T), True), T)
            End If

            '返す
            Return CType(_Instance, T)

        End SyncLock

    End Function

End Class

派生クラス

SingletonA.vb
''' <summary>
''' 派生クラスA
''' </summary>
''' <remarks></remarks>
Public Class SingletonA
    Inherits AbstractSingletonClass(Of SingletonA)

    ''' <summary>
    ''' コンストラクタ(Protected)
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub New()

    End Sub

End Class

使い方

'型推論が効く!!
Dim S = SingletonA.GetInstance()

え??これじゃ静的フィールドの_Instanceを入れ替えてるんだから2個目、3個目の派生クラスのインスタンスが保持れないでしょ?と指摘したのだが「いや、イケてますww」との返事。・・・確かに。

今回勉強になったポイント

ジェネリクスの静的フィールドの場合、型毎に保持される。

参考:ジェネリッククラス内の静的フィールドの挙動について

なので、ディクショナリを使わずとも1つの型に対して別々の静的フィールドが割り当てられるためインスタンスを正しく保持することができる。

残る問題

以前のクラスでは扱う型を基底クラスの派生に制限していたが、今回はクラス宣言の時点で型を決めるため制限することができない。
・・・が、そもそも制限しなければいけない理由が見つからなかった。結局、単に派生しただけではSingletonは保証されるわけではなく、派生先のコンスタラクタを隠すことを忘れてしまうと複数のインスタンスが生成可能になってしまう。(これを強制する仕組みは今のところ無い?)

最終的には

問題点よりもいちいちGetInstanceを書かなくてよい、インスタンス生成に型推論が効くということの恩恵の方がはるかに大きいので改訂版を使用することに決めた。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?