Lazy(T) Clase
TOC
Collapse the table of content
Expand the table of content
Este artículo se tradujo automáticamente. Para ver el artículo en inglés, active la casilla Inglés. Además, puede mostrar el texto en inglés en una ventana emergente si mueve el puntero del mouse sobre el texto.
Traducción
Inglés

Lazy<T> (Clase)

 

Proporciona compatibilidad para la inicialización diferida.

Espacio de nombres:   System
Ensamblado:  mscorlib (en mscorlib.dll)


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

Parámetros de tipo

T

Tipo de objeto que se inicializa de forma diferida.

NombreDescripción
System_CAPS_pubmethodLazy<T>()

Inicializa una nueva instancia de la clase Lazy<T>. Cuando se produce la inicialización diferida, se usa el constructor predeterminado del tipo de destino.

System_CAPS_pubmethodLazy<T>(Boolean)

Inicializa una nueva instancia de la clase Lazy<T>. Cuando se produce la inicialización diferida, se usan el constructor predeterminado del tipo de destino y el modo de inicialización especificado.

System_CAPS_pubmethodLazy<T>(Func<T>)

Inicializa una nueva instancia de la clase Lazy<T>. Cuando se produce la inicialización diferida, se usa la función de inicialización especificada.

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

Inicializa una nueva instancia de la clase Lazy<T>. Cuando se produce la inicialización diferida, se usan la función de inicialización y el modo de inicialización especificados.

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

Inicializa una nueva instancia de la clase Lazy<T> que usa la función de inicialización especificada y el modo de seguridad para subprocesos.

System_CAPS_pubmethodLazy<T>(LazyThreadSafetyMode)

Inicializa una nueva instancia de la clase Lazy<T> que usa el constructor predeterminado de T y el modo de seguridad para subprocesos especificado.

NombreDescripción
System_CAPS_pubpropertyIsValueCreated

Obtiene un valor que indica si se se creó un valor para esta instancia Lazy<T>.

System_CAPS_pubpropertyValue

Obtiene el valor inicializado de forma diferida de la instancia actual de Lazy<T>.

NombreDescripción
System_CAPS_pubmethodEquals(Object)

Determina si el objeto especificado es igual al objeto actual.(Heredado de Object.)

System_CAPS_protmethodFinalize()

Permite que un objeto intente liberar recursos y realizar otras operaciones de limpieza antes de ser reclamado por el recolector de basura. (Heredado de Object.)

System_CAPS_pubmethodGetHashCode()

Sirve como la función hash predeterminada.(Heredado de Object.)

System_CAPS_pubmethodGetType()

Obtiene el Type de la instancia actual.(Heredado de Object.)

System_CAPS_protmethodMemberwiseClone()

Crea una copia superficial del Object actual.(Heredado de Object.)

System_CAPS_pubmethodToString()

Crea y devuelve una representación de cadena de la propiedad Lazy<T>.Value de esta instancia.(Reemplaza a Object.ToString()).

Utilizar la inicialización diferida para aplazar la creación de un objeto grande o que consumen muchos recursos, o la ejecución de una tarea que consume muchos recursos, especialmente cuando esa creación o ejecución podría no producirse durante la vigencia del programa.

Para prepararse para la inicialización diferida, se crea una instancia de Lazy<T>. El argumento de tipo de la Lazy<T> objeto que cree especifica el tipo del objeto que se va a inicializar de forma diferida. El constructor que se utiliza para crear la Lazy<T> objeto determina las características de la inicialización. La inicialización diferida se produce la primera vez el Lazy<T>.Value acceso a la propiedad.

En la mayoría de los casos, la elección de un constructor depende de sus respuestas a dos preguntas:

  • ¿Se el objeto inicializado de forma diferida obtenerse acceso desde varios subprocesos? Si es así, la Lazy<T> objeto puede crear en cualquier subproceso. Puede utilizar uno de los constructores simples cuyo comportamiento predeterminado es crear un subprocesos Lazy<T> de objeto, por lo que solo una instancia de objeto con instancias de forma diferida se crea independientemente de cuántos subprocesos intentan obtener acceso a él. Para crear un Lazy<T> objeto que no es seguro para subprocesos, debe utilizar un constructor que le permite no especificar ninguna seguridad para subprocesos.

    System_CAPS_cautionPrecaución

    Realizar la Lazy<T> seguro para subprocesos de objeto no protege el objeto inicializado de forma diferida. Si varios subprocesos pueden tener acceso al objeto inicializado de forma diferida, debe realizar sus propiedades y métodos seguros para el acceso multiproceso.

  • ¿Inicialización diferida requiere una gran cantidad de código o el objeto inicializado de forma diferida tiene un constructor predeterminado que hace todo lo que necesita y no produce excepciones? Si necesita escribir el código de inicialización o si necesitan controlar excepciones, use uno de los constructores que toma un método de fábrica. Escribir el código de inicialización en el método de fábrica.

La siguiente tabla muestra qué constructor para elegir, en función de estos dos factores:

Objeto tendrán acceso a

Si se requiere ningún código de inicialización (constructor predeterminado), utilizar

Si se requiere código de inicialización, utilice

Varios subprocesos

Lazy<T>()

Lazy<T>(Func<T>)

Un subproceso

Lazy<T>(Boolean) con isThreadSafe establecido en false.

Lazy<T>(Func<T>, Boolean) con isThreadSafe establecido en false.

Puede usar una expresión lambda para especificar el método de fábrica. Esto evita que el código de inicialización en un solo lugar. La expresión lambda captura el contexto, incluidos los argumentos que se pasa al constructor del objeto inicializado de forma diferida.

El almacenamiento en caché de excepción  cuando se usan métodos de fábrica, las excepciones se almacenan en caché. Es decir, si el método de fábrica produce un tiempo de excepción primero un subproceso intenta obtener acceso a la Value propiedad de la Lazy<T> del objeto, la misma excepción se produce en cada intento subsiguiente. Esto garantiza que cada llamada a la Value propiedad produce el mismo resultado y evita errores sutiles que pueden surgir si diferentes subprocesos obtengan resultados diferentes. La Lazy<T> significa un real T que de lo contrario, habría inicializado en algún momento anterior, normalmente durante el inicio. Un error en ese momento anterior es suele ser desastroso. Si existe la posibilidad de un error recuperable, se recomienda crear la lógica de reintento en la rutina de inicialización (en este caso, el método de fábrica), como haría si no hubiera usado la inicialización diferida.

Alternativa al bloqueo  en determinadas situaciones, puede evitar la sobrecarga de la Lazy<T> objeto predeterminado el comportamiento de bloqueo. En raras ocasiones, podría ser un riesgo de interbloqueo. En tales casos, puede utilizar el Lazy<T>(LazyThreadSafetyMode) o Lazy<T>(Func<T>, LazyThreadSafetyMode) constructor y especifique LazyThreadSafetyMode.PublicationOnly. Esto permite la Lazy<T> objeto para crear una copia del objeto inicializado de forma diferida en cada uno de varios subprocesos si llama los subprocesos del Value propiedad simultáneamente. La Lazy<T> objeto garantiza que todos los subprocesos, utilizar la misma instancia del objeto inicializado de forma diferida y descarta las instancias que no se utilizan. Por lo tanto, el costo de reducir la sobrecarga de bloqueo es que el programa podría crear y descartar copias adicionales de un objeto caro a veces. En la mayoría de los casos, esto es improbable. Los ejemplos de la Lazy<T>(LazyThreadSafetyMode) y Lazy<T>(Func<T>, LazyThreadSafetyMode) constructores muestran este comportamiento.

System_CAPS_importantImportante

Cuando se especifica PublicationOnly, las excepciones no están nunca en caché, incluso si se especifica un método de fábrica.

Equivalente constructores  además de habilitar el uso de PublicationOnly, Lazy<T>(LazyThreadSafetyMode) y Lazy<T>(Func<T>, LazyThreadSafetyMode) constructores pueden duplicar la funcionalidad de los otros constructores. En la tabla siguiente se muestra los valores de parámetro que generan un comportamiento equivalente.

Para crear un Lazy<T> objeto que se

Para los constructores que tienen un LazyThreadSafetyMode mode establecido mode

Constructores que tienen un valor booleano de isThreadSafe establecido isThreadSafe a

Para los constructores sin parámetros de seguridad del subproceso

Totalmente seguro para subprocesos; utiliza el bloqueo para garantizar que sólo un subproceso inicializa el valor.

ExecutionAndPublication

true

Todos estos constructores están completamente segura para subprocesos.

No es seguro para subprocesos.

None

false

No disponible.

Totalmente seguro para subprocesos; carrera de subprocesos para inicializar el valor.

PublicationOnly

No disponible.

No es aplicable.

Otras capacidades  para obtener información sobre el uso de Lazy<T> con campos de subproceso estático, o como el almacén de respaldo para las propiedades, consulte Lazy Initialization.

En el ejemplo siguiente se muestra el uso de la Lazy<T> clase para proporcionar la inicialización diferida con acceso desde varios subprocesos.

System_CAPS_noteNota

El ejemplo utiliza el Lazy<T>(Func<T>) constructor. También se muestra el uso de la Lazy<T>(Func<T>, Boolean) constructor (especificar true para isThreadSafe) y la Lazy<T>(Func<T>, LazyThreadSafetyMode) constructor (especificar LazyThreadSafetyMode.ExecutionAndPublication para mode). Para cambiar a un constructor diferente, cambie los constructores que están comentados.

Para obtener un ejemplo que muestra la excepción de almacenamiento en caché con los constructores de la mismos, consulte el Lazy<T>(Func<T>) constructor.

El ejemplo define una clase LargeObject que uno de varios subprocesos inicializará de forma diferida. Las cuatro secciones claves de código muestran la creación de inicializador, el método de fábrica, la inicialización real y el constructor de la LargeObject (clase), que muestra un mensaje cuando se crea el objeto. Al principio del método Main, el ejemplo crea el inicializador diferido seguro para subprocesos para 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);

El método de fábrica muestra la creación del objeto, con un marcador de posición para la inicialización adicional:

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

Tenga en cuenta que las secciones de dos primeras código se pueden combinar mediante una función lambda, como se muestra aquí:

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

El ejemplo se detiene, para indicar que puede transcurrir un período indeterminado antes de que se produce la inicialización diferida. Cuando se presiona el ENTRAR clave, el ejemplo crea e inicia tres subprocesos. El ThreadProc método utilizado por todas las llamadas de tres subprocesos el Value propiedad. La primera vez que esto ocurre, el LargeObject se crea la instancia:

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

El constructor de la LargeObject (clase), que incluye la última sección clave del código, se muestra un mensaje y se registra la identidad del subproceso de inicialización. El resultado del programa aparece al final de la lista de código completa.

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

Por simplificar, en este ejemplo se emplea una instancia global de Lazy<T> y todos los métodos son static (Shared en Visual Basic). No son requisitos para el uso de la inicialización diferida.

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
Disponible desde 4.5
.NET Framework
Disponible desde 4.0
Portable Class Library
Compatible con: portable .NET platforms
Silverlight
Disponible desde 4.0
Windows Phone Silverlight
Disponible desde 8.0
Windows Phone
Disponible desde 8.1

De forma predeterminada, todos los miembros públicos y protegidos de la Lazy<T> clase son seguros para subprocesos y se pueden usar desde varios subprocesos simultáneamente. Estas garantías de seguridad de los subprocesos pueden eliminarse, opcionalmente y por instancia, utilizando parámetros a los constructores del tipo.

Volver al principio
Mostrar:
© 2016 Microsoft