web-dev-qa-db-ja.com

C#のシングルトンとは何ですか?

かなり簡単な質問です。

シングルトンとは何ですか?いつ使用する必要がありますか?

161
Sergio Tapia

シングルトンは、自身のインスタンスを1つだけ作成できるクラスであり、そのインスタンスへのシンプルで簡単なアクセスを提供します。シングルトンの前提は、ソフトウェア開発全体にわたるパターンです。

C#の実装があります 「C#でシングルトンパターンを実装する」 知っておくべきことのほとんどをカバーしています-スレッドの安全性に関するいくつかの良いアドバイスを含みます

正直に言うと、シングルトンを実装する必要があることは非常にまれです-私の意見では、あまり頻繁に使用されていなくても、あなたが知っておくべきことの1つでなければなりません。

130
Daniel May

C#を要求しました。簡単な例:


public class Singleton
{
    private Singleton()
    {
        // Prevent outside instantiation
    }

    private static readonly Singleton _singleton = new Singleton();

    public static Singleton GetSingleton()
    {
        return _singleton;
    }
}
48
Chris Simmons

それが何であるか:アプリケーションの存続期間中、永続インスタンスが1つだけ存在するクラス。 シングルトンパターン を参照してください。

使用する場合:できるだけ少なくします。あなたがそれを必要とする絶対に確信している場合のみ。私は「決して」とは言いたがりませんが、通常、依存性注入や単純な静的クラスなど、より良い代替手段があります。

39
Aaronaught

c#でシングルトンを実装する別の方法では、メソッドの代わりにプロパティとしてシングルトンクラスのインスタンスにアクセスできるため、個人的にこの方法を好みます。

public class Singleton
    {
        private static Singleton instance;

        private Singleton() { }

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

        //instance methods
    }

しかし、まあ、私が知る限り、両方の方法は「正しい」と考えられているので、それは個人的な趣味のものです。

24
Marnix v. R.
using System;
using System.Collections.Generic;
class MainApp
{
    static void Main()
    {
        LoadBalancer oldbalancer = null;
        for (int i = 0; i < 15; i++)
        {
            LoadBalancer balancerNew = LoadBalancer.GetLoadBalancer();

            if (oldbalancer == balancerNew && oldbalancer != null)
            {
                Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);
            }
            oldbalancer = balancerNew;
        }
        Console.ReadKey();
    }
}

class LoadBalancer
{
    private static LoadBalancer _instance;
    private List<string> _servers = new List<string>();
    private Random _random = new Random();

    private static object syncLock = new object();

    private LoadBalancer()
    {
        _servers.Add("ServerI");
        _servers.Add("ServerII");
        _servers.Add("ServerIII");
        _servers.Add("ServerIV");
        _servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
        if (_instance == null)
        {
            lock (syncLock)
            {
                if (_instance == null)
                {
                    _instance = new LoadBalancer();
                }
            }
        }

        return _instance;
    }

    public string Server
    {
        get
        {
            int r = _random.Next(_servers.Count);
            return _servers[r].ToString();
        }
    }
}

私は dofactory.com からコードを取得しましたが、それほど素晴らしいものではありませんが、FooとBarの例よりもはるかに良いことがわかりますC#3.0のJudith BishopによるDesign Patternsには、Macドックでのアクティブなアプリケーションの例があります。

コードを見ると、実際にはforループで新しいオブジェクトを構築しているため、新しいオブジェクトを作成しますが、その結果としてインスタンスを再利用します。その結果、oldbalancerとnewbalancer同じインスタンスがありますか?そのため、関数で使用されるstaticキーワードGetLoadBalancer()にもかかわらず、ランダムリストである別のサーバー値を使用すると、static onGetLoadBalancer()は特定のオブジェクトではなくタイプ自体に属します。

さらに、 ダブルチェックロック があります

if (_instance == null)
            {
                lock (syncLock)
                {
                    if (_instance == null)

mSDNから

Lockキーワードは、あるスレッドがコードのクリティカルセクションに入らないようにし、別のスレッドがクリティカルセクションにあるようにします。別のスレッドがロックされたコードを入力しようとすると、オブジェクトが解放されるまでブロックされます。

そのため、不要な場合でも相互排除ロックが毎回発行されるため、nullチェックがあります。

願わくば、それがもっとクリアに役立つことを願っています。

そして、私の理解が間違った方向を示している場合、コメントしてください。

10
brykneval

シングルトン(これはC#に結び付けられておらず、OOデザインパターンです)は、アプリケーション全体でクラスのインスタンスを1つだけ作成できるようにする場合です。使用には通常、グローバルリソースが含まれますが、私は個人的な経験から言いますが、非常に頻繁に大きな痛みの原因になります。

6
BFree

シングルトンのインスタンスは1つしか存在できませんが、静的クラスとは異なります。静的クラスには静的メソッドのみを含めることができ、インスタンス化することはできませんが、シングルトンのインスタンスは他のオブジェクトと同じように使用できます。

5
TabbyCool

ルックアップデータに使用します。 DBから一度ロードします。

public sealed class APILookup
    {
        private static readonly APILookup _instance = new APILookup();
        private Dictionary<string, int> _lookup;

        private APILookup()
        {
            try
            {
                _lookup = Utility.GetLookup();
            }
            catch { }
        }

        static APILookup()
        {            
        }

        public static APILookup Instance
        {
            get
            {
                return _instance;
            }
        }
        public Dictionary<string, int> GetLookup()
        {
            return _lookup;
        }

    }
2
Manish Jain

これはデザインパターンであり、c#に固有のものではありません。これについての詳細は、インターネットとSO全体で wikipediaの記事 のように。

ソフトウェアエンジニアリングでは、シングルトンパターンは、クラスのインスタンス化を1つのオブジェクトに制限するために使用される設計パターンです。これは、システム全体でアクションを調整するために正確に1つのオブジェクトが必要な場合に役立ちます。概念は、オブジェクトが1つだけ存在する場合により効率的に動作するシステム、またはインスタンス化を特定の数のオブジェクト(5つなど)に制限するシステムに一般化されることがあります。それをアンチパターンと見なし、使いすぎだと判断し、クラスの唯一のインスタンスが実際に必要とされない状況で不必要な制限を導入し、アプリケーションにグローバルな状態を導入します。

一度だけインスタンス化できるクラスが必要な場合は、これを使用する必要があります。

2
marcgg

シングルトンとは:
これは、自身のインスタンスを1つだけ作成できるクラスであり、通常はそのインスタンスへの簡単なアクセスを提供します。

を使用する場合
状況によって異なります。

注:詳細な回答については、DB接続では使用しないでください 参照 @Chad Grantの回答

以下はSingletonの簡単な例です。

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

Lazy<T>を使用してSingletonを作成することもできます。

こちらを参照Lazy<T>を使用したより詳細な例

2
MSTdev

シングルトンとは次のとおりです。 http://en.wikipedia.org/wiki/Singleton_pattern

私はC#を知りませんが、実際にはすべての言語で同じことであり、実装のみが異なります。

一般に、可能であればシングルトンは避けるべきですが、状況によっては非常に便利です。

私の英語でごめんなさい;)

1
radex

シングルトンクラスは、アプリケーションドメイン全体の単一のインスタンスを作成するために使用されます。

public class Singleton
{
    private static Singleton singletonInstance = CreateSingleton();

    private Singleton()
    {
    }

    private static Singleton CreateSingleton()
    {
        if (singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }

        return singletonInstance;
    }

    public static Singleton Instance
    {
        get { return singletonInstance; }            
    }
}

この記事で説明されています読み取り専用変数を使用してスレッドセーフなシングルトンクラスを作成する方法と、アプリケーションでの実用化.

1
Vikram

特定のクラスのインスタンスが1つだけ作成されるようにする必要がある場合は、C#でシングルトンデザインパターンを使用し、アプリケーション全体に対してそのインスタンスへの単純なグローバルアクセスを提供する必要があります。

シングルトンデザインパターンを使用できるリアルタイムシナリオ:サービスプロキシ:知っているように、サービスAPIの呼び出しは、アプリケーションでの広範な操作です。ほとんどの時間を要するプロセスは、サービスAPIを呼び出すためにサービスクライアントを作成することです。サービスプロキシをシングルトンとして作成すると、アプリケーションのパフォーマンスが向上します。

ファサード:データベース接続をシングルトンとして作成して、アプリケーションのパフォーマンスを向上させることもできます。

ログ:アプリケーションでは、ファイルでI/O操作を実行するのは高価な操作です。ロガーをシングルトンとして作成すると、I/O操作のパフォーマンスが向上します。

データ共有:定数値または構成値がある場合は、これらの値をシングルトンに保持して、アプリケーションの他のコンポーネントが読み取れるようにすることができます。

キャッシュ:データベースからデータを取得するのは時間のかかるプロセスです。アプリケーションでは、マスターと構成をメモリにキャッシュして、DB呼び出しを回避できます。このような状況では、Singletonクラスを使用して、スレッド同期によるキャッシュを効率的な方法で処理し、アプリケーションのパフォーマンスを大幅に改善できます。

C#のシングルトンデザインパターンの短所C#でシングルトンデザインパターンを使用する短所は次のとおりです。

単体テストは、アプリケーションにグローバルな状態を導入するため、非常に困難です。マルチスレッド環境でシングルトンインスタンスにアクセスするには、ロックを使用してオブジェクトをシリアル化する必要があるため、プログラム内の並列処理の可能性が低下します。

次の記事からこれを取り上げました。

https://dotnettutorials.net/lesson/singleton-design-pattern/

0
Pranaya Rout

私は質問に答えるのが非常に遅いことを知っていますが、自動プロパティを使用すると、そのようなことができます:

public static Singleton Instance { get; } = new Singleton();

Singletonはクラスであり、経由することができます。この場合は、読み取り専用プロパティInstanceです。

0
Zyo

E.X注入する必要があるグローバル情報にシングルトンを使用できます。

私の場合、Loggedユーザーの詳細(ユーザー名、アクセス許可など)をGlobal Static Classに保持していました。そして、ユニットテストを実装しようとしたとき、Controllerクラスに依存関係を挿入する方法がありませんでした。したがって、静的クラスをシングルトンパターンに変更しました。

public class SysManager
{
    private static readonly SysManager_instance = new SysManager();

    static SysManager() {}

    private SysManager(){}

    public static SysManager Instance
    {
        get {return _instance;}
    }
}

http://csharpindepth.com/Articles/General/Singleton.aspx#cctor

0
n3xus