web-dev-qa-db-ja.com

vbのシングルトンパターン

私は通常c#プログラマーですが、シングルトンクラスのセットアップに使用する場合、この1つのプロジェクトでVB)で作業しています。JonSkeetモデルに従います。

public sealed class Singleton
{
    static Singleton instance = null;
    static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }

    //Added to illustrate the point
    public static void a()
    {
    }

    public void b()
    {
    }

} 

または、c#でステートメントを記述した場合のバリエーションの1つ

Singleton.Instance静的ではなく、bではなくaではないすべてのメンバーの手順は何ですか。

今私がVBで同じことをするとき

Private Shared _instance As StackTracker
Private Shared ReadOnly _lock As Object = New Object()
Private Sub New()
    _WorkingStack = New Stack(Of MethodObject)
    _HistoryStack = New Queue(Of MethodObject)
End Sub

Public Shared ReadOnly Property Instance() As StackTracker
    Get
        SyncLock _lock
            If (_instance Is Nothing) Then
                _instance = New StackTracker()
            End If
        End SyncLock

        Return _instance
    End Get

End Property

StackTracker.Instance.Instanceそしてそれは進み続けます、それは世界の終わりではありませんが、それは悪く見えます。

質問VBに2番目のインスタンスを非表示にして、ユーザーがインスタンスを再帰的に呼び出せないようにする方法はありますか?

15
Mike

完全なコードは次のとおりです。

Public NotInheritable Class MySingleton
    Private Shared ReadOnly _instance As New Lazy(Of MySingleton)(Function() New
        MySingleton(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)

    Private Sub New()
    End Sub

    Public Shared ReadOnly Property Instance() As MySingleton
        Get
            Return _instance.Value
        End Get
    End Property
End Class

次に、このクラスを使用するには、次を使用してインスタンスを取得します。

Dim theSingleton As MySingleton = MySingleton.Instance
12
rundavidrun

これは実際にはジョンが出した提案ではありません。 この問題に関する記事で参照されている3番目のバージョン を実装しましたが、メモリバリアがないため、EMCA仕様に従って機能しないと彼は指摘しています。

むしろ、ネストされたクラスを使用し、ネストされたクラスの静的フィールドの宣言でインスタンスの割り当てを実行する5番目のバージョンを使用する必要があります。

.NET 4.0で作業している場合は、これを行う必要はありません。タイプ Lazy<T> の静的読み取り専用フィールドを作成し、 LazyThreadSafetyMode.ExecutionAndPublication をコンストラクターに渡すことができます(Func<T>とともに、方法を示します)インスタンスを作成するには)値が1回だけ作成されることを保証します。

次に、 Lazy<T>.Value property を呼び出すだけのプロパティを公開して、遅延読み込みされたシングルトン値を返します。

5
casperOne

元の質問は、シングルトンパターンを実装する方法についてではなく、C#では、インスタンスを介して静的メンバーにアクセスしようとするとコンパイラエラーになるという事実に言及していました。現在のVBでは警告です。

解決策:プロジェクトコンパイラの設定を「すべての警告をエラーとして扱う」に変更できますが、警告42025だけをエラーとして明示的に扱う方法がわかりません。

そうは言っても、VBにシングルトンを実装するもっと簡単な方法もあります。

public class Singleton
    private sub new()
    end sub

    public shared readonly property Instance as Singleton
        get
            static INST as Singleton = new Singleton
            return INST
        end get
    end property
end class

これは、C#にはない機能である静的変数のVBスレッドセーフな単一初期化に依存しています。「静的」という単語で始まるコード行は、インスタンスプロパティであっても1回だけ評価されます。多くのスレッドから何度もアクセスされます。

3
JustinMichel

何かが足りないかもしれませんが、クラスで他に何が起こっているかに応じて、これにいくつかのバリエーションを加えます。

Class MySingleton

    'The instance initializes once and persists (provided it's not intentionally destroyed)
    Private Shared oInstance As MySingleton = New MySingleton

    'A property initialized via the Create method
    Public Shared Property SomeProperty() As Object = Nothing

   'Constructor cannot be called directly so prevents external instantiation
    Private Sub New()
        'Nothing to do
    End Sub

    'The property returns the single instance
    Public Shared ReadOnly Property Instance As MySingleton
        Get
            Return oInstance
        End Get
    End Property

    'The method returns the single instance while also initializing SomeProperty
    Public Shared Function Create(
        ByVal SomeParam As Object) As MySingleton

        _SomeProperty = SomeParam
        Return oInstance
    End Function
End Class

明らかに、通常はどちらかInstanceプロパティまたはCreateメソッドのみを提供し、両方は提供しません(ただし、必要に応じて提供することもできます)。何らかの理由で)。

最も単純な形式では、次のとおりです。

Class MySingleton

    Private Shared oInstance As MySingleton = New MySingleton

    Private Sub New()
    End Sub

    Public Shared ReadOnly Property Instance As MySingleton
        Get
            Return oInstance
        End Get
    End Property
End Class
1
SteveCinq