この記事は機械翻訳されています。英語版の記事を表示するには、[英語] のチェック ボックスをオンにしてください。また、テキストにマウス ポインターを合わせると、ポップアップ ウィンドウに英語のテキストを表示することもできます。
翻訳
英語

Lazy<T> クラス

 

公開日: 2016年10月

遅延初期化のサポートを提供します。

名前空間:   System
アセンブリ:  mscorlib (mscorlib.dll 内)


[SerializableAttribute]
[ComVisibleAttribute(false)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
	ExternalThreading = true)]
public class Lazy<T>

型パラメーター

T

遅延初期化されているオブジェクトの型。

名前説明
System_CAPS_pubmethodLazy<T>()

Lazy<T> クラスの新しいインスタンスを初期化します。 遅延初期化が発生した場合は、ターゲット型の既定のコンストラクターが使用されます。

System_CAPS_pubmethodLazy<T>(Boolean)

Lazy<T> クラスの新しいインスタンスを初期化します。 遅延初期化が発生すると、ターゲット型の既定のコンストラクターおよび指定した初期化モードが使用されます。

System_CAPS_pubmethodLazy<T>(Func<T>)

Lazy<T> クラスの新しいインスタンスを初期化します。 遅延初期化が発生すると、指定された初期化関数が使用されます。

System_CAPS_pubmethodLazy<T>(Func<T>, Boolean)

Lazy<T> クラスの新しいインスタンスを初期化します。 遅延初期化が発生すると、指定された初期化関数と初期化モードが使用されます。

System_CAPS_pubmethodLazy<T>(Func<T>, LazyThreadSafetyMode)

指定された初期化関数とスレッド セーフ モードを使用する Lazy<T> クラスの新しいインスタンスを初期化します。

System_CAPS_pubmethodLazy<T>(LazyThreadSafetyMode)

T の既定のコンストラクターと指定されたスレッド セーフ モードを使用する Lazy<T> クラスの新しいインスタンスを初期化します。

名前説明
System_CAPS_pubpropertyIsValueCreated

この Lazy<T> インスタンスに対して値が作成されているかどうかを示す値を取得します。

System_CAPS_pubpropertyValue

現在の Lazy<T> インスタンスの遅れて初期化される値を取得します。

名前説明
System_CAPS_pubmethodEquals(Object)

指定したオブジェクトが、現在のオブジェクトと等しいかどうかを判断します。(Object から継承されます。)

System_CAPS_protmethodFinalize()

オブジェクトが、ガベージ コレクションによって収集される前に、リソースの解放とその他のクリーンアップ操作の実行を試みることができるようにします。(Object から継承されます。)

System_CAPS_pubmethodGetHashCode()

既定のハッシュ関数として機能します。(Object から継承されます。)

System_CAPS_pubmethodGetType()

現在のインスタンスの Type を取得します。(Object から継承されます。)

System_CAPS_protmethodMemberwiseClone()

現在の Object の簡易コピーを作成します。(Object から継承されます。)

System_CAPS_pubmethodToString()

このインスタンスの Lazy<T>.Value プロパティの文字列形式を作成して返します。(Object.ToString() をオーバーライドします。)

特に、このような作成または実行が、プログラムの有効期間中に実行されない場合に、大規模またはリソースを消費するオブジェクトの作成またはリソースを消費するタスクの実行を延期するのに限定的な初期化を使用します。

インスタンスを作成する限定的な初期化の準備として、 Lazy<T>です。 型引数、 Lazy<T> を作成するオブジェクトは、遅延初期化するオブジェクトの種類を指定します。 作成するために使用するコンス トラクター、 Lazy<T> オブジェクトが初期化の特性を決定します。 限定的な初期化が初めて発生した、 Lazy<T>.Value プロパティにアクセスします。

ほとんどの場合は、2 つの質問に対する回答に依存コンス トラクターを選択します。

  • 遅れて初期化されるオブジェクトは、複数のスレッドからアクセスされるでしょうか。 その場合、 Lazy<T> オブジェクトを使用するとすべてのスレッドに作成できます。 既定の動作は、スレッド セーフを作成する簡単なコンス トラクターのいずれかを使用する Lazy<T> オブジェクトのため、アクセスしようとしているスレッドの数に関係なく、遅延インスタンス化されたオブジェクトの 1 つのインスタンスを作成します。 作成する、 Lazy<T> スレッド セーフではないオブジェクトの場合は、スレッド セーフ no を指定することができますコンス トラクターを使用する必要があります。

    System_CAPS_caution注意

    作成、 Lazy<T> スレッド セーフでオブジェクトが、遅れて初期化されるオブジェクトを保護しません。 複数のスレッドが、遅れて初期化されるオブジェクトにアクセスできる場合が必要プロパティとメソッド マルチ スレッド アクセスについて安全です。

  • 限定的な初期化が不要多くのコードに遅れて初期化されるオブジェクトがすべて必要があるし、例外をスローせず、既定のコンス トラクターか。 初期化コードを記述する必要がある場合、または例外を処理する必要がある場合は、ファクトリ メソッドを受け取るコンス トラクターのいずれかを使用します。 ファクトリ メソッドには、初期化コードを記述します。

これら 2 つの要因に基づいて選択するにはどのコンス トラクターを次の表に示します。

アクセスされるオブジェクト

初期化コードが必要ない場合 (既定のコンス トラクター) を使用して

初期化コードが必要な場合は、使用します。

複数のスレッド

Lazy<T>()

Lazy<T>(Func<T>)

1 つのスレッド

Lazy<T>(Boolean) isThreadSafe 設定 falseします。

Lazy<T>(Func<T>, Boolean) isThreadSafe 設定 falseします。

ラムダ式を使用すると、ファクトリ メソッドを指定します。 これにより、すべての初期化コードが 1 か所に保持されます。 ラムダ式では、遅れて初期化されるオブジェクトのコンス トラクターに渡す引数も含めて、コンテキストをキャプチャします。

例外キャッシュ  ファクトリ メソッドを使用する場合、例外がキャッシュされます。 つまり、ファクトリ メソッドが例外の最初の時間をスローした場合、スレッドにアクセスしよう、 Value のプロパティ、 Lazy<T> オブジェクト、後続するたびに、同じ例外がスローされます。 これにより、すべての呼び出しに、 Value プロパティは、同じ結果を生成して、別のスレッドが異なる結果を得る場合に生じる可能性のある微妙なエラーを回避できます。 Lazy<T> 、実際の代わりに T をそれ以外の場合は初期化されているある以前の時点での起動中に通常です。 その以前の時点でのエラーでは、通常致命的です。 回復可能な障害発生する可能性がある場合は、限定的な初期化を使用していなかった場合と同様、(ここでは、ファクトリ メソッド)、初期化ルーチンに再試行ロジックを構築することをお勧めします。

をロックする代わりに  特定の状況でのオーバーヘッドを回避することがあります、 Lazy<T> オブジェクトの既定のロック動作します。 まれな状況でデッドロックの可能性があります。 このような場合に使用することができます、 Lazy<T>(LazyThreadSafetyMode) または Lazy<T>(Func<T>, LazyThreadSafetyMode) コンス トラクターを指定して LazyThreadSafetyMode.PublicationOnlyします。 これにより、 Lazy<T> 、スレッドを呼び出す場合、複数のスレッドの各遅れて初期化されるオブジェクトのコピーを作成するオブジェクト、 Value プロパティ同時にします。 Lazy<T> オブジェクトにより、すべてのスレッドが、遅れて初期化されるオブジェクトの同じインスタンスを使用し、使用されていないインスタンスを破棄します。 したがって、ロックのオーバーヘッドを軽減するのにかかるコストは、プログラムの作成し、負荷の高いオブジェクトの余分なコピーを破棄することがある場合もありますです。 ほとんどの場合、これはほとんどありません。 例として、 Lazy<T>(LazyThreadSafetyMode)Lazy<T>(Func<T>, LazyThreadSafetyMode) コンス トラクターは、この動作をについて説明します。

System_CAPS_important重要

指定すると PublicationOnly, 、ファクトリ メソッドを指定した場合でも、例外はキャッシュしないでされます。

相当するコンス トラクター  の使用を有効にするだけでなく PublicationOnly, 、 Lazy<T>(LazyThreadSafetyMode)Lazy<T>(Func<T>, LazyThreadSafetyMode) コンス トラクターは、他のコンス トラクターの機能を複製することができます。 次の表は、同等の動作を生成するパラメーター値を示します。

作成する、 Lazy<T> オブジェクトを

コンス トラクターを持つ、 LazyThreadSafetyMode mode パラメーターを設定する mode に 

ブール値を持つコンス トラクターの isThreadSafe パラメーターを設定する isThreadSafe

スレッド セーフのパラメーターなしのコンス トラクター

スレッド セーフでは完全に使用して、その 1 つのスレッドをロックでは、値を初期化します。

ExecutionAndPublication

true

このようなすべてのコンス トラクターは、スレッド セーフでは完全にします。

いないスレッド セーフであります。

None

false

該当しない。

スレッド セーフでは完全に値を初期化するためにスレッド競合します。

PublicationOnly

該当しない。

該当なし。

その他の機能  の使用については Lazy<T> スレッド内静的フィールドを持つ、またはプロパティのバッキング ストアとして 限定的な初期化します。

次の例では、使用、 Lazy<T> クラスを複数のスレッドからのアクセスを限定的な初期化を提供します。

System_CAPS_noteメモ

例では、 Lazy<T>(Func<T>) コンス トラクターです。 使用についても示します、 Lazy<T>(Func<T>, Boolean) コンス トラクター (を指定する trueisThreadSafe) および Lazy<T>(Func<T>, LazyThreadSafetyMode) コンス トラクター (を指定する LazyThreadSafetyMode.ExecutionAndPublicationmode)。 別のコンス トラクターに切り替えると、同じどのコンス トラクターをコメント アウトを変更します。

例外を示す例については、同じコンス トラクターを使用して、キャッシュを参照してください、 Lazy<T>(Func<T>) コンス トラクターです。

この例では、複数あるスレッドのうちの 1 つによって遅れて初期化される LargeObject クラスを定義します。 コードの 4 つの主要セクションが、初期化子、ファクトリ メソッド、実際の初期化およびのコンス トラクターの作成を示す、 LargeObject クラスは、オブジェクトの作成時にメッセージが表示されます。 Main メソッドの開始時に、この例では LargeObject のスレッドセーフな遅延初期化子が作成されます。

lazyLargeObject = new Lazy<LargeObject>(InitLargeObject);

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line: 
//lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, true);
//lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, 
//                               LazyThreadSafetyMode.ExecutionAndPublication);

ファクトリ メソッドより詳細な初期化のプレース ホルダーで、オブジェクトの作成を示しています。

static LargeObject InitLargeObject()
{
    LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId);
    // Perform additional initialization here.
    return large;
}

次に示すように、最初の 2 つのコードのセクションでは、でしたラムダ関数を使用してによって組み合わせて指定することに注意してください。

lazyLargeObject = new Lazy<LargeObject>(() => 
{
    LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId);
    // Perform additional initialization here.
    return large;
});

例では、限定的な初期化が行われる前に、不確定な期間が切れることがありますを示すために一時停止します。 押すと、 Enter キー、例を作成して 3 つのスレッドを開始します。 ThreadProc 3 つのスレッドのすべての呼び出しで使用されるメソッド、 Value プロパティです。 このシナリオは、最初に、 LargeObject インスタンスを作成します。

LargeObject large = lazyLargeObject.Value;

// IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the  
//            object after creation. You must lock the object before accessing it,
//            unless the type is thread safe. (LargeObject is not thread safe.)
lock(large)
{
    large.Data[0] = Thread.CurrentThread.ManagedThreadId;
    Console.WriteLine("Initialized by thread {0}; last used by thread {1}.", 
        large.InitializedBy, large.Data[0]);
}

コンス トラクター、 LargeObject クラスは、コードの最後の主要セクションが含まれているメッセージが表示され、初期化中のスレッドの id を記録します。 完全なコード リストの最後に、プログラムからの出力が表示されます。

int initBy = 0;
public LargeObject(int initializedBy)
{
    initBy = initializedBy;
    Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
}
System_CAPS_noteメモ

簡略化のために、この例では Lazy<T> のグローバル インスタンスを使用して、すべてのメソッドは static (Visual Basic の Shared) です。 これらは、遅延初期化を使用するための要件ではありません。

using System;
using System.Threading;

class Program
{
    static Lazy<LargeObject> lazyLargeObject = null;

    static LargeObject InitLargeObject()
    {
        LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId);
        // Perform additional initialization here.
        return large;
    }


    static void Main()
    {
        // The lazy initializer is created here. LargeObject is not created until the 
        // ThreadProc method executes.
        lazyLargeObject = new Lazy<LargeObject>(InitLargeObject);

        // The following lines show how to use other constructors to achieve exactly the
        // same result as the previous line: 
        //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, true);
        //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, 
        //                               LazyThreadSafetyMode.ExecutionAndPublication);


        Console.WriteLine(
            "\r\nLargeObject is not created until you access the Value property of the lazy" +
            "\r\ninitializer. Press Enter to create LargeObject.");
        Console.ReadLine();

        // Create and start 3 threads, each of which uses LargeObject.
        Thread[] threads = new Thread[3];
        for (int i = 0; i < 3; i++)
        {
            threads[i] = new Thread(ThreadProc);
            threads[i].Start();
        }

        // Wait for all 3 threads to finish. 
        foreach (Thread t in threads)
        {
            t.Join();
        }

        Console.WriteLine("\r\nPress Enter to end the program");
        Console.ReadLine();
    }


    static void ThreadProc(object state)
    {
        LargeObject large = lazyLargeObject.Value;

        // IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the  
        //            object after creation. You must lock the object before accessing it,
        //            unless the type is thread safe. (LargeObject is not thread safe.)
        lock(large)
        {
            large.Data[0] = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Initialized by thread {0}; last used by thread {1}.", 
                large.InitializedBy, large.Data[0]);
        }
    }
}

class LargeObject
{
    public int InitializedBy { get { return initBy; } }

    int initBy = 0;
    public LargeObject(int initializedBy)
    {
        initBy = initializedBy;
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
    }

    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject.

LargeObject was created on thread id 3.
Initialized by thread 3; last used by thread 3.
Initialized by thread 3; last used by thread 4.
Initialized by thread 3; last used by thread 5.

Press Enter to end the program
 */

ユニバーサル Windows プラットフォーム
8 以降で使用可能
.NET Framework
4.0 以降で使用可能
ポータブル クラス ライブラリ
サポート対象: 移植可能 .NET プラットフォーム
Silverlight
4.0 以降で使用可能
Windows Phone Silverlight
8.0 以降で使用可能
Windows Phone
8.1 以降で使用可能

既定では、すべてのパブリック、プロテクト メンバーの Lazy<T> クラスはスレッド セーフであると、複数のスレッドから同時に使用される場合があります。 これらのスレッド セーフの保証は、必要に応じて、型のコンス トラクターにパラメーターを使用して、インスタンスごとに削除できます。

トップに戻る
表示: