Come eseguire l'inizializzazione pigra in C #

L'inizializzazione pigra è una tecnica che differisce la creazione di un oggetto fino alla prima volta che è necessario. In altre parole, l'inizializzazione dell'oggetto avviene solo su richiesta. Si noti che i termini inizializzazione lenta e istanziazione lenta hanno lo stesso significato: possono essere usati in modo intercambiabile. Sfruttando l'inizializzazione lenta, è possibile migliorare le prestazioni dell'applicazione evitando calcoli non necessari e consumo di memoria. In questo articolo vedremo come eseguire l'inizializzazione lenta in C #.

Comprendiamo il caricamento pigro con un semplice esempio. Considera due classi Customere Order. La Customerclasse contiene una Ordersproprietà che a sua volta fa riferimento a una raccolta di istanze della Orderclasse. La Ordersraccolta può contenere una grande quantità di dati e potrebbe anche richiedere una connessione al database per connettersi al database e recuperare i record. In tal caso, non ha senso caricare i dati nella Ordersproprietà finché non abbiamo bisogno dei dati. L'inizializzazione lenta ci consente di caricare la Ordersraccolta solo quando vengono richiesti i dati.

Utilizzo della classe Lazy in C #

Sebbene sia possibile scrivere il proprio codice personalizzato per implementare l'inizializzazione lenta, Microsoft consiglia di utilizzare Lazyinvece la classe. La Lazyclasse nello Systemspazio dei nomi in C # è stata introdotta come parte di .Net Framework 4.0 per fornire un modo thread-safe per implementare l'inizializzazione lenta. È possibile sfruttare questa classe per rinviare l'inizializzazione di oggetti a elevato utilizzo di risorse nell'applicazione.

Quando si utilizza la Lazyclasse, è necessario specificare il tipo di oggetto che si intende creare pigramente nell'argomento tipo. Notare che l'inizializzazione lenta si verifica quando si accede alla Lazy.Valueproprietà. Ecco un esempio di come Lazyè possibile utilizzare la classe:

Pigro
   
     ordini = nuovo pigro
    
     ();
     

IEnumerable result = lazyOrders.Value;

Consideriamo ora due classi Authore Blog. Un autore può scrivere molti post sul blog, quindi hai una relazione uno-a-molti tra le classi Authore Blogcome mostrato nello snippet di codice di seguito.

public class Autore

    {

        public int Id {get; impostato; }

        stringa pubblica FirstName {get; impostato; }

        stringa pubblica LastName {get; impostato; }

        stringa pubblica Indirizzo {get; impostato; }

        Elenco blog pubblico {get; impostato; }

    }

    blog di classe pubblica

    {

        public int Id {get; impostato; }

        stringa pubblica Titolo {get; impostato; }

        public DateTime PublicationDate {get; impostato; }

    }

Si noti che la relazione uno-a-molti tra le classi Authore Blogè stata rappresentata utilizzando una Listproprietà (di tipo Blog) nella Authorclasse. Utilizzando questa proprietà, la Authorclasse può contenere una raccolta di una o più istanze della Blogclasse.

Supponiamo ora di dover visualizzare solo i dettagli di un autore (nome, cognome e indirizzo) nell'interfaccia utente. In questo caso non ha senso caricare i dettagli del blog per l'autore; vogliamo caricare pigramente i dettagli del blog. Ecco la Authorclasse aggiornata che risponde a questa esigenza. Nota l'uso della Lazyclasse.

public class Autore

    {

        public int Id {get; impostato; }

        stringa pubblica FirstName {get; impostato; }

        stringa pubblica LastName {get; impostato; }

        stringa pubblica Indirizzo {get; impostato; }

        pubblico pigro Blog => nuovo Lazy (() => GetBlogDetailsForAuthor (this.Id));

        IList privato GetBlogDetailsForAuthor (int Id)

        {

       // Scrivi qui il codice per recuperare tutti i dettagli del blog per un autore.

        }

    }

Utilizzo della classe Lazy generica in C #

Vediamo ora come possiamo trarre vantaggio da una Lazyclasse generica per implementare il modello di progettazione Singleton. (Puoi leggere il mio articolo sul modello di progettazione Singleton qui.) La seguente versione della StateManagerclasse è thread-safe. Allo stesso tempo, dimostra l'inizializzazione lenta. Si noti che il costruttore statico esplicito è stato utilizzato per garantire che il compilatore C # non contrassegni il tipo come beforefieldinit.

Classe pubblica sigillata StateManager

    {

        StateManager privato ()

        {

        }

        istanza statica pubblica di StateManager

        {

            ottenere

            {

                return Nested.obj;

            }

        }

        classe privata Annidato

        {

            statico annidato ()

            {

            }

            statico interno di sola lettura StateManager obj = new StateManager ();

        }

    }

Ecco un'implementazione pigra della StateManagerclasse che sfrutta la Lazyclasse. Puoi vedere come la Lazyclasse rende davvero semplice implementare la pigrizia. 

public class StateManager

    {

        privato statico di sola lettura Lazy obj = new Lazy (() => new StateManager ());

        private StateManager () {}

        istanza statica pubblica di StateManager

        {

            ottenere

            {

                return obj.Value;

            }

        }

    }

Dai un'occhiata alla Instanceproprietà nella StateManagerclasse sopra. Nota che la Valueproprietà che vedi nell'esempio di codice sopra è di sola lettura. Per questo motivo non esiste una funzione di accesso impostata.

L'inizializzazione lenta è un'eccellente tecnica di ottimizzazione delle prestazioni, che consente di rinviare l'inizializzazione di oggetti che consumano notevoli risorse di CPU e memoria fino a quando non ne hai assolutamente bisogno. Approfitta dell'inizializzazione lenta per migliorare le prestazioni delle tue app.