Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Classe Lazy<T>

 

Data di pubblicazione: ottobre 2016

Fornisce il supporto per l'inizializzazione differita.

Spazio dei nomi:   System
Assembly:  mscorlib (in mscorlib.dll)


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

Parametri tipo

T

Tipo di oggetto che viene inizializzato in modo differito.

NomeDescrizione
System_CAPS_pubmethodLazy<T>()

Inizializza una nuova istanza della classe Lazy<T>. Quando si verifica l'inizializzazione differita, viene usato il costruttore predefinito del tipo di destinazione.

System_CAPS_pubmethodLazy<T>(Boolean)

Inizializza una nuova istanza della classe Lazy<T>. Quando si verifica l'inizializzazione differita, vengono usati il costruttore predefinito del tipo di destinazione e la modalità di inizializzazione specificata.

System_CAPS_pubmethodLazy<T>(Func<T>)

Inizializza una nuova istanza della classe Lazy<T>. Quando si verifica l'inizializzazione differita, viene usata la funzione specificata.

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

Inizializza una nuova istanza della classe Lazy<T>. Quando si verifica l'inizializzazione differita, vengono usate la funzione e la modalità di inizializzazione specificate.

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

Inizializza una nuova istanza della classe Lazy<T> che usa la funzione di inizializzazione e la modalità thread safety specificate.

System_CAPS_pubmethodLazy<T>(LazyThreadSafetyMode)

Inizializza una nuova istanza della classe Lazy<T> che usa il costruttore predefinito di T e la modalità thread safety specificati.

NomeDescrizione
System_CAPS_pubpropertyIsValueCreated

Ottiene un valore che indica se è stato creato un valore per l'istanza di Lazy<T>.

System_CAPS_pubpropertyValue

Ottiene il valore con inizializzazione differita dell'istanza corrente di Lazy<T>.

NomeDescrizione
System_CAPS_pubmethodEquals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object.)

System_CAPS_protmethodFinalize()

Consente a un oggetto di provare a liberare risorse ed eseguire altre operazioni di pulizia prima che l'oggetto stesso venga reclamato dalla procedura di Garbage Collection. (Ereditato da Object.)

System_CAPS_pubmethodGetHashCode()

Funge da funzione hash predefinita.(Ereditato da Object.)

System_CAPS_pubmethodGetType()

Ottiene l'oggetto Type dell'istanza corrente.(Ereditato da Object.)

System_CAPS_protmethodMemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.(Ereditato da Object.)

System_CAPS_pubmethodToString()

Crea e restituisce una rappresentazione di stringa della proprietà Lazy<T>.Value per questa istanza.(Esegue l'override di Object.ToString().)

Utilizzare l'inizializzazione differita per rinviare la creazione di un oggetto di grandi dimensioni o risorse o l'esecuzione di un'attività a elevato utilizzo di risorse, in particolare quando tale creazione o esecuzione potrebbe non verificarsi durante la durata del programma.

Per preparare per l'inizializzazione differita, si crea un'istanza di Lazy<T>. L'argomento di tipo di Lazy<T> che l'oggetto creato specifica il tipo dell'oggetto che si desidera inizializzare in modo differito. Il costruttore che consente di creare il Lazy<T> oggetto determina le caratteristiche dell'inizializzazione. Inizializzazione differita si verifica la prima volta il Lazy<T>.Value si accede alla proprietà.

Nella maggior parte dei casi, la scelta di un costruttore dipende le risposte alle due domande:

  • Verrà eseguito l'oggetto inizializzato in modo differito da più thread? In questo caso, il Lazy<T> oggetto potrebbe creare in qualsiasi thread. È possibile utilizzare uno dei costruttori semplici il cui comportamento predefinito consiste nel creare un thread-safe Lazy<T> dell'oggetto, in modo che solo un'istanza dell'oggetto in modo differito un'istanza viene creata indipendentemente da quanti thread tenta di accedervi. Per creare un Lazy<T> oggetto che non è thread-safe, è necessario utilizzare un costruttore che consente di non specificare thread-safe.

    System_CAPS_cautionAttenzione

    Effettua il Lazy<T> affidabile oggetto non consente di proteggere l'oggetto inizializzato in modo differito. Se più thread possono accedere all'oggetto inizializzato in modalità differita, è necessario apportare le proprietà e metodi sicuri per l'accesso multithreading.

  • Inizializzazione differita richiede una grande quantità di codice o l'oggetto inizializzato in modo differito privo di un costruttore predefinito che esegue le operazioni necessarie è necessario e non genera eccezioni? Se è necessario scrivere codice di inizializzazione o se le eccezioni devono essere gestite, utilizzare uno dei costruttori che accettano un metodo factory. Scrivere il codice di inizializzazione nel metodo factory.

Nella tabella seguente viene illustrato quale costruttore di scegliere, in base a questi due fattori:

L'accesso all'oggetto verrà effettuato da

Se è richiesto alcun codice di inizializzazione (costruttore predefinito), utilizzare

Se il codice di inizializzazione è necessario, utilizzare

Più thread

Lazy<T>()

Lazy<T>(Func<T>)

Un thread

Lazy<T>(Boolean) con isThreadSafe impostato su false.

Lazy<T>(Func<T>, Boolean) con isThreadSafe impostato su false.

È possibile utilizzare un'espressione lambda per specificare il metodo factory. In questo modo tutto il codice di inizializzazione in un'unica posizione. L'espressione lambda acquisisce il contesto, inclusi gli eventuali argomenti passati al costruttore dell'oggetto inizializzato in modalità differita.

La memorizzazione nella cache di eccezione  quando si utilizzano metodi factory, le eccezioni vengono memorizzate nella cache. Ovvero, se il metodo factory genera un'ora la prima eccezione un thread tenta di accedere il Value proprietà del Lazy<T> dell'oggetto, la stessa eccezione viene generata a ogni tentativo successivo. Ciò garantisce che ogni chiamata alla Value proprietà produce lo stesso risultato e consente di evitare errori difficili da rilevare che potrebbero verificarsi se diversi thread ottengano risultati diversi. Il Lazy<T> è l'acronimo di una vera e propria T che altrimenti sarebbe sono stati inizializzati in precedenza, in genere durante l'avvio. Un errore al momento precedente rappresenta in genere un errore irreversibile. Se è presente un potenziale di un errore reversibile, è consigliabile compilare la logica di ripetizione in routine di inizializzazione (in questo caso, il metodo factory), così come accadrebbe se non è stato utilizzato l'inizializzazione differita.

Alternativa al blocco  In determinate situazioni, si desidera evitare il sovraccarico di Lazy<T> comportamento di blocco predefinito dell'oggetto. In rari casi, potrebbe esserci un rischio di deadlock. In questi casi, è possibile utilizzare il Lazy<T>(LazyThreadSafetyMode) o Lazy<T>(Func<T>, LazyThreadSafetyMode) costruttore e specificare LazyThreadSafetyMode.PublicationOnly. In questo modo il Lazy<T> oggetto per creare una copia dell'oggetto inizializzato in modo differito in ognuno dei diversi thread se il thread chiama il Value proprietà contemporaneamente. Il Lazy<T> oggetto garantisce che tutti i thread di utilizzare la stessa istanza dell'oggetto inizializzato in modo differito ed Elimina le istanze che non vengono utilizzate. Pertanto, il costo di ridurre l'overhead dei blocchi è che il programma potrebbe talvolta creare e rimuovere le copie aggiuntive di un oggetto dispendioso. Nella maggior parte dei casi, ciò è improbabile. Gli esempi per il Lazy<T>(LazyThreadSafetyMode) e Lazy<T>(Func<T>, LazyThreadSafetyMode) costruttori illustrano questo comportamento.

System_CAPS_importantImportante

Quando si specifica PublicationOnly, le eccezioni non vengono mai memorizzati nella cache, anche se si specifica un metodo factory.

Costruttori equivalenti  oltre a consentire l'utilizzo di PublicationOnly, Lazy<T>(LazyThreadSafetyMode) e Lazy<T>(Func<T>, LazyThreadSafetyMode) costruttori possono duplicare la funzionalità degli altri costruttori. Nella tabella seguente vengono illustrati i valori di parametro che producono un comportamento equivalente.

Per creare un Lazy<T> oggetto

Per i costruttori che dispongono di un LazyThreadSafetyMode mode set di parametri, mode

Per i costruttori che dispongono di un valore booleano isThreadSafe set di parametri, isThreadSafe a

Per i costruttori senza parametri di sicurezza del thread

Completamente thread-safe. utilizza il blocco per garantire che un solo thread Inizializza il valore.

ExecutionAndPublication

true

Tutti questi costruttori sono completamente thread-safe.

Non i thread-safe.

None

false

Non applicabile.

Completamente thread-safe. i thread concorrono per inizializzare il valore.

PublicationOnly

Non applicabile.

Non applicabile.

Altre funzionalità  per informazioni sull'utilizzo di Lazy<T> con i campi statici thread o come archivio di backup per le proprietà, vedere Lazy Initialization.

Nell'esempio seguente viene illustrato l'utilizzo della Lazy<T> classe per fornire l'inizializzazione differita con accesso da più thread.

System_CAPS_noteNota

Nell'esempio viene utilizzata la Lazy<T>(Func<T>) costruttore. Viene inoltre illustrato l'utilizzo del Lazy<T>(Func<T>, Boolean) costruttore (specificando true per isThreadSafe) e Lazy<T>(Func<T>, LazyThreadSafetyMode) costruttore (specificando LazyThreadSafetyMode.ExecutionAndPublication per mode). Per passare a un altro costruttore, è sufficiente impostare come commento costruttori.

Per un esempio di eccezione la memorizzazione nella cache usando i costruttori stesso, vedere il Lazy<T>(Func<T>) costruttore.

Nell'esempio viene definita una classe LargeObject che verrà inizializzata in modo differito da uno dei diversi thread. Quattro sezioni principali di codice illustrano la creazione dell'inizializzatore, il metodo factory, l'inizializzazione effettiva e il costruttore della LargeObject classe, che viene visualizzato un messaggio quando viene creato l'oggetto. All'inizio del metodo Main, viene creato un inizializzatore thread-safe differito per 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);

Il metodo factory viene illustrata la creazione dell'oggetto, con un segnaposto per un'ulteriore inizializzazione:

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

Si noti che le sezioni di codice primi due possono essere combinate usando una funzione lambda, come illustrato di seguito:

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

Consente di sospendere l'esempio, per indicare che un periodo di tempo indeterminato potrebbe trascorrere prima che venga eseguita l'inizializzazione differita. Quando si preme il INVIO chiave, l'esempio crea e avvia tre thread. Il ThreadProc metodo utilizzato da tutte le chiamate tre thread di Value proprietà. La prima volta in questo caso, il LargeObject creata l'istanza:

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

Il costruttore della LargeObject classe, che include l'ultima chiave sezione di codice, viene visualizzato un messaggio e registra l'identità del thread durante l'inizializzazione. L'output del programma viene visualizzato alla fine dell'elenco di codice completo.

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

Per semplicità, in questo esempio viene utilizzata un'istanza globale di Lazy<T> e tutti i metodi sono static (Shared in Visual Basic). Questi non sono requisiti per l'uso di inizializzazione differita.

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

Universal Windows Platform
Disponibile da 8
.NET Framework
Disponibile da 4.0
Libreria di classi portabile
Supportato in: piattaforme .NET portabili
Silverlight
Disponibile da 4.0
Windows Phone Silverlight
Disponibile da 8.0
Windows Phone
Disponibile da 8.1

Per impostazione predefinita, tutti i membri pubblici e protetti della Lazy<T> classe sono thread-safe e possono essere utilizzati contemporaneamente da più thread. È possibile rimuovere queste garanzie di thread safety, facoltativamente e per ogni istanza, utilizzando i parametri nei costruttori del tipo.

Torna all'inizio
Mostra: