Durante la scrittura di classi spesso si definisco proprietà che fanno uso di membri privati per mantenere valori e riferimenti, e nel metodo di get si tende a posticipare l'inizializzazione del membro solo quando si accede effettivamente alla proprietà. Per implementare tale meccanismo si controlla semplicemente se il campo è nullo e lo si valorizza, come nell'esempio seguente:
private MyObject _data; public MyObject Data { get { if (_data == null) _data = new MyObject(); return _data; } }
Le cose si complicano quando la proprietà può essere acceduta da più thread contemporaneamente e si vuole essere sicuri di avere un'unica istanza dell'oggetto. In questo caso il singleton pattern prevede dei meccanismi di controllo e di lock che sono ripetitivi. Nel .NET framework 4.0 viene in aiuto la classe Lazy<T> che compie tutte queste operazioni automaticamente. Ecco quindi come diventa la nuova implementazione della proprietà:
private Lazy<MyObject> _data = new Lazy<MyObject>(); public MyObject Data { get { return _data.Value; } }
Questa classe generica gestisce all'interno della proprietà Value i meccanismi necessari ad instanziare MyObject in modo sicuro. Per default infatti Value è thread safe, ma possiamo indicare attraverso LazyThreadSafetyMode se la proprietà Value dev'essere sicura solo per la pubblicazione (PublicationOnly: l'oggetto potrebbe essere instanziato più di una volta, ma solo un'istanza verrà scelta) o sia per la pubblicazione e l'esecuzione (ExecutionAndPublication: l'istanza e la proprietà sono una sola).
Facoltativamente è possibile passare un delegate ad una funzione da richiamare per instanziare e inizializzare l'oggetto:
private Lazy<MyObject> _data = new Lazy<MyObject>(() => new MyObject("test"));
Infine, con la classe statica LazyInitializer è possibile inizializzare in modo thread safe l'argomento passato per riferimento.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.