Dieser Artikel wurde maschinell übersetzt. Wenn Sie die englische Version des Artikels anzeigen möchten, aktivieren Sie das Kontrollkästchen Englisch. Sie können den englischen Text auch in einem Popupfenster anzeigen, indem Sie den Mauszeiger über den Text bewegen.
Übersetzung
Englisch

Lazy<T>-Klasse

.NET Framework (current version)
 

Veröffentlicht: Oktober 2016

Bietet Unterstützung für die verzögerte Initialisierung.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)


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

Typparameter

T

Der Typ des Objekts, das verzögert initialisiert wird.

NameBeschreibung
System_CAPS_pubmethodLazy<T>()

Initialisiert eine neue Instanz der Lazy<T>-Klasse. Wenn eine verzögerte Initialisierung auftritt, wird der Standardkonstruktor des Zieltyps verwendet.

System_CAPS_pubmethodLazy<T>(Boolean)

Initialisiert eine neue Instanz der Lazy<T>-Klasse. Bei einer verzögerten Initialisierung werden der Standardkonstruktor des Zieltyps und der angegebene Initialisierungsmodus verwendet.

System_CAPS_pubmethodLazy<T>(Func<T>)

Initialisiert eine neue Instanz der Lazy<T>-Klasse. Bei einer verzögerten Initialisierung wird die angegebene Initialisierungsfunktion verwendet.

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

Initialisiert eine neue Instanz der Lazy<T>-Klasse. Bei einer verzögerten Initialisierung werden die angegebene Initialisierungsfunktion und der angegebene Initialisierungsmodus verwendet.

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

Initialisiert eine neue Instanz der Lazy<T>-Klasse, die die angegebene Initialisierungsfunktion und den angegebenen Threadsicherheitsmodus verwendet.

System_CAPS_pubmethodLazy<T>(LazyThreadSafetyMode)

Initialisiert eine neue Instanz der Lazy<T>-Klasse, die den Standardkonstruktor von T und den angegebenen Threadsicherheitsmodus verwendet.

NameBeschreibung
System_CAPS_pubpropertyIsValueCreated

Ruft einen Wert ab, der angibt, ob ein Wert für diese Lazy<T>-Instanz erstellt wurde.

System_CAPS_pubpropertyValue

Ruft den verzögert initialisierten Wert der aktuellen Lazy<T>-Instanz ab.

NameBeschreibung
System_CAPS_pubmethodEquals(Object)

Bestimmt, ob das angegebene Objekt mit dem aktuellen Objekt identisch ist.(Geerbt von „Object“.)

System_CAPS_protmethodFinalize()

Gibt einem Objekt Gelegenheit, Ressourcen freizugeben und andere Bereinigungen durchzuführen, bevor es von der Garbage Collection freigegeben wird. (Geerbt von „Object“.)

System_CAPS_pubmethodGetHashCode()

Fungiert als die Standardhashfunktion.(Geerbt von „Object“.)

System_CAPS_pubmethodGetType()

Ruft den Type der aktuellen Instanz ab.(Geerbt von „Object“.)

System_CAPS_protmethodMemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.(Geerbt von „Object“.)

System_CAPS_pubmethodToString()

Erstellt eine Zeichenfolgendarstellung der Lazy<T>.Value-Eigenschaft für diese Instanz und gibt diese zurück.(Überschreibt Object.ToString().)

Verwenden Sie verzögerten Initialisierung, um die Erstellung eines großen oder ressourcenintensiven Objekts oder die Ausführung einer ressourcenintensiven Aufgabe verzögern, insbesondere, wenn eine solche Erstellung oder Ausführung möglicherweise nicht während der Lebensdauer des Programms auftritt.

Um für die verzögerte Initialisierung vorzubereiten, erstellen Sie eine Instanz des Lazy<T>. Das Typargument der Lazy<T> -Objekt, das Sie erstellen, gibt den Typ des Objekts, das Sie verzögert initialisieren möchten. Der Konstruktor, mit dem Erstellen, der Lazy<T> Objekt bestimmt die Merkmale der Initialisierung. Verzögerter Initialisierung erfolgt zum ersten Mal die Lazy<T>.Value -Eigenschaft zugegriffen wird.

In den meisten Fällen hängt die Antworten auf zwei Fragen einen Konstruktor auswählen:

  • Wird das verzögert initialisierte Objekt von mehreren Threads werden zugegriffen? In diesem Fall die Lazy<T> Objekt kann auf einem beliebigen Thread erstellen. Können Sie die einfache Konstruktoren, deren Standardverhalten ist, erstellen Sie ein threadsicheres Lazy<T> Objekt, so dass nur eine Instanz des verzögert instanziierten Objekts erstellt wird, unabhängig davon, wie viele Threads versuchen, darauf zuzugreifen. Erstellen einer Lazy<T> Objekt, das nicht threadsicher ist, müssen Sie einen Konstruktor, der Ihnen ermöglicht, die keine Threadsicherheit angeben verwenden.

    System_CAPS_cautionAchtung

    Erstellen der Lazy<T> Objekt threadsicher schützt nicht die verzögert initialisierte Objekt. Wenn mehrere Threads, die verzögert initialisierte Objekt zugreifen können, müssen Sie dessen Eigenschaften und Methoden für Multithreadzugriff sicher.

  • Erfordert verzögerter Initialisierung viel Code, oder verfügt das verzögert initialisierte Objekt über einen Standardkonstruktor, die alles, was Sie benötigen, und löst keine Ausnahmen aus? Verwenden Sie Wenn Sie schreiben Code für die Initialisierung müssen oder Ausnahmen behandelt werden müssen, die Konstruktoren, die eine Factory-Methode akzeptiert. Schreiben Sie den Initialisierungscode in der Factory-Methode.

Die folgende Tabelle zeigt die Konstruktor auswählen, auf Basis dieser zwei Faktoren:

Objekt wird von zugegriffen werden

Wenn kein Initialisierungscode erforderlich ist (Standard-Konstruktor) verwenden

Wenn Code für die Initialisierung erforderlich ist, verwenden.

Mehrere threads

Lazy<T>()

Lazy<T>(Func<T>)

Ein thread

Lazy<T>(Boolean) mit isThreadSafe festgelegt false.

Lazy<T>(Func<T>, Boolean) mit isThreadSafe festgelegt false.

Einen Lambda-Ausdruck können die Factorymethode. Dadurch wird den Initialisierungscode an einem Ort. Der Lambda-Ausdruck erfasst Kontexts, einschließlich der Argumente ein, die Sie an der verzögert initialisierte-Objektkonstruktor übergeben.

Ausnahme caching  bei Verwendung von Factorymethoden Ausnahmen werden zwischengespeichert. D. h. wenn die Factory-Methode löst eine Ausnahme beim ersten Mal aus, ein Thread versucht, Zugriff auf die Value Eigenschaft der Lazy<T> -Objekt, die gleiche Ausnahme wird bei jedem nachfolgenden Versuch ausgelöst. Dadurch wird sichergestellt, dass jeder Aufruf der Value Eigenschaft führt zum gleichen Ergebnis, und vermeidet Fehler auftreten, die auftreten können, wenn verschiedene Threads unterschiedliche Ergebnisse zu erhalten. Die Lazy<T> stellvertretend für eine tatsächliche T andernfalls würde initialisiert wurden früher irgendwann in der Regel während des Starts. Ein Fehler bei der frühere Zeitpunkt ist in der Regel Schwerwiegender. Ist möglicherweise mit einem behebbaren Fehler, wird empfohlen, dass Sie die Wiederholungslogik in die Initialisierungsroutine (in diesem Fall die Factory-Methode), erstellen, wie wenn Sie verzögerten Initialisierung verwenden würden.

Alternative zum Sperren  In bestimmten Situationen möchten vermeiden Sie den Aufwand für die Lazy<T> des Objekts Standard Sperrverhalten. In seltenen Fällen kann eine Wahrscheinlichkeit für Deadlocks vorhanden sein. In solchen Fällen können Sie die Lazy<T>(LazyThreadSafetyMode) oder Lazy<T>(Func<T>, LazyThreadSafetyMode) -Konstruktor, und geben Sie LazyThreadSafetyMode.PublicationOnly. Auf diese Weise können die Lazy<T> -Objekt, das eine Kopie der verzögert initialisierte Objekt auf jedem von mehreren Threads zu erstellen, wenn die Threads Aufrufen der Value Eigenschaft gleichzeitig. Das Lazy<T> Objekt wird sichergestellt, dass alle Threads dieselbe Instanz des Objekts verzögert initialisierte und verwirft die Instanzen, die nicht verwendet werden. Daher ist die Kosten der Aufwand für das Sperren reduzieren, dass das Programm möglicherweise manchmal erstellen und, zusätzliche Kopien der ein teures Objekt verwerfen. In den meisten Fällen ist dies wahrscheinlich nicht. Beispiele für die Lazy<T>(LazyThreadSafetyMode) und Lazy<T>(Func<T>, LazyThreadSafetyMode) Konstruktoren veranschaulichen dieses Verhalten.

System_CAPS_importantWichtig

Beim Angeben von PublicationOnly, Ausnahmen werden nie zwischengespeichert, selbst wenn Sie eine Factory-Methode angeben.

Entsprechende Konstruktoren  zusätzlich zum Aktivieren der Verwendung von PublicationOnly, Lazy<T>(LazyThreadSafetyMode) und Lazy<T>(Func<T>, LazyThreadSafetyMode) Konstruktoren können die Funktionalität von den anderen Konstruktoren duplizieren. Die folgende Tabelle zeigt die Parameterwerte, die ein gleichwertiges Verhalten zu erzeugen.

Erstellen einer Lazy<T> -Objekts

Für Konstruktoren, haben eine LazyThreadSafetyMode mode Parameter festlegen, mode

Für Konstruktoren, die einen booleschen Wert haben isThreadSafe Parameter festlegen, isThreadSafe

Für Konstruktoren mit Parametern kein Thread-Sicherheit

Vollständig threadsicher; verwendet sperren, um sicherzustellen, dass nur ein Thread den Wert initialisiert.

ExecutionAndPublication

true

Alle diese Konstruktoren sind vollständig threadsicher.

Nicht threadsicher.

None

false

Nicht zutreffend.

Vollständig threadsicher; Threads Rennen um den Wert zu initialisieren.

PublicationOnly

Nicht zutreffend.

Nicht zutreffend.

Andere Funktionen  Informationen über die Verwendung von Lazy<T> mit threadstatische Felder oder als Sicherungsspeicher für Eigenschaften, finden Sie unter Lazy Initialization.

Das folgende Beispiel veranschaulicht die Verwendung von der Lazy<T> -Klasse, verzögerten Initialisierung beim Zugriff von mehreren Threads bereitzustellen.

System_CAPS_noteHinweis

Im Beispiel wird die Lazy<T>(Func<T>) Konstruktor. Es veranschaulicht auch die Verwendung von der Lazy<T>(Func<T>, Boolean) Konstruktor (angeben true für isThreadSafe) und die Lazy<T>(Func<T>, LazyThreadSafetyMode) Konstruktor (Angabe LazyThreadSafetyMode.ExecutionAndPublication für mode). Um einen anderen Konstruktor zu wechseln, ändern Sie einfach die Konstruktoren auskommentiert werden.

Ein Beispiel für die Ausnahme mithilfe der gleichen Konstruktoren finden Sie unter der Lazy<T>(Func<T>) Konstruktor.

Im Beispiel wird eine LargeObject-Klasse definiert, die durch einen von mehreren Threads verzögert initialisiert wird. Die vier wichtigsten Abschnitte des Codes veranschaulichen die Erstellung der Initialisierer, die Factory-Methode, die eigentliche Initialisierung und den Konstruktor von der LargeObject -Klasse, die eine Meldung angezeigt, wenn das Objekt erstellt wird. Zu Anfang der Main-Methode wird in diesem Beispiel ein threadsicherer verzögerter Initialisierer für LargeObject erstellt:

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);

Die Factory-Methode zeigt die Erstellung des Objekts, mit einem Platzhalter für die weitere Initialisierung:

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

Beachten Sie, dass die ersten zwei Codeabschnitte mithilfe einer Lambda-Funktion kombiniert werden können, wie hier gezeigt:

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

Im Beispiel wird angehalten, um anzugeben, dass für ein unbestimmter Zeitraum abläuft, bevor die verzögerte Initialisierung auftritt. Beim Drücken der EINGABETASTE Schlüssel, das Beispiel erstellt und startet drei Threads. Die ThreadProc -Methode, alle drei Threads Aufrufe der Value Eigenschaft. Beim ersten in diesem Fall die LargeObject Instanz erstellt wird:

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]);
}

Der Konstruktor für die LargeObject -Klasse, die der letzten Abschnitt des Codes enthält, wird eine Meldung angezeigt, und zeichnet die Identität des Threads initialisieren. Die Ausgabe des Programms wird am Ende der vollständige Beispielcode angezeigt.

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

Der Einfachheit halber wird in diesem Beispiel eine globale Instanz von Lazy<T> verwendet, und alle Methoden sind static (Shared in Visual Basic). Dies sind keine Anforderungen für die Verwendung der verzögerten Initialisierung.

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
 */

Universelle Windows-Plattform
Verfügbar seit 8
.NET Framework
Verfügbar seit 4.0
Portierbare Klassenbibliothek
Unterstützt in: portierbare .NET-Plattformen
Silverlight
Verfügbar seit 4.0
Windows Phone Silverlight
Verfügbar seit 8.0
Windows Phone
Verfügbar seit 8.1

In der Standardeinstellung werden alle öffentlichen und geschützten Member von der Lazy<T> -Klasse sind threadsicher und können von mehreren Threads gleichzeitig verwendet werden. Diese Threadsicherheit Garantien können optional und pro Instanz des Typs Konstruktoren entfernt werden.

Zurück zum Anfang
Anzeigen: