posts - 644, comments - 2003, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

Singleton senza static (o shared se preferite)

Il pattern singleton è forse uno dei più conosciuti e consiste nel limitare una classe ad una sola istanza e che questa sia accessibile pubblicamente.

Il modo più semplice per implementare un singleton è quello di definire una classe in questo modo:

// Singleton in C# 1.x
public sealed class MyClass   // sealed evita che sia derivabile
{
  private MyClass {}  // costruttore privato per evitare che la classe sia istanziabile
  public static int MyMethod(int x, int y) {return x+y;} // Metodo statico
}
Dove posso usare la forma MyClass.MyMethod(2, 3);

In C# 2.0 la forma è più elegante ma pressochè identica:
public static class MyClass  // static sulla classe obbliga tutti i suoi metodi ad essere statici
{
  public static int MyMethod(int x, int y) {return x+y;} // Metodo statico
}

Ma se volessimo un singleton che obbedisca a un contratto stabilito da interfacce? Per una serie di ottimi motivi ben descritti su msdn e in vari blog sulla rete non è possibile definire delle interfacce 'statiche'.

La soluzione è banale e già pluriusata all'epoca COM non troppo lontana ma ormai con dotnet siamo abituati troppo bene e così ecco una delle possibili implementazioni alternative.

 // Singleton implementato senza static (C# 1.x)
 public sealed class MyClass
 {
  private static MyClass _mySelf = null;
  public static MyClass GetInstance()
  {
   if(_mySelf == null)
    _mySelf = new MyClass();
   return _mySelf;
  }
  private MyClass() {}
 }

Con questa implementazione viene creata l'unica istanza grazie al factory pattern e successivamente restituita sempre la stessa istanza. Da notare che in questo modo, contrariamente alla soluzione con static, è possibile implementare con poche righe aggiuntive del codice che butti via l'istanza. Così facendo non ci sarà più neppure l'unica istanza disponibile che verrà riallocata appena richiesta la volta successiva.

Print | posted on mercoledì 12 gennaio 2005 23:39 | Filed Under [ .NET [Italiano] ]

Feedback

Gravatar

# re: Singleton senza static (o shared se preferite)

Di solito io utilizzo l'approccio che hai indicato senza usare i metodi static, facendo static solo il metodo factory...
13/01/2005 00:50 | Lorenzo Barbieri
Gravatar

# re: Singleton senza static (o shared se preferite)

Spesso utilizzo

static readonly MyClass instance = new MyClass();

e se di visibilità pubblica wrappata da una property

Questo per semplicità e per evitarmi la sincronizzazione che andrebbe fatta con il metodo GetInstance



13/01/2005 01:38 | Massimo Prota
Gravatar

# re: Singleton senza static (o shared se preferite)

Ciao Raffaele

Personalmente il tuo primo esempio non lo vedo proprio come un singleton...

Se vuoi aggiungere un metodo instance nel tuo primo esempio non puoi perché manca il campo Instance che ti fornisca un'istanza (unica) di MyClass. Mentre nell'implementazione qui sotto (oppure in quella dell'ultimo esempio) puoi avere anche metodi instance

public sealed class Singleton
{
private Singleton(){}
public static readonly Singleton Instance = new Singleton();
}

Le classi static nella v.2.0 non sono tutte singleton - secondo me :-)
13/01/2005 03:09 | Adrian Florea
Gravatar

# re: Singleton senza static (o shared se preferite)

Ciao Adrian,
tecnicamente parlando le classi statiche rispondono al requisito di singleton:
- che esista una sola istanza
- istanza sia facilmente accessibile
Possiamo discutere su cosa si intenda per 'istanza' ma di fatto tutto ciò che è static viene allocato la prima volta che la classe viene usata e viene disallocata al termine dell'applicazione. Visto che allocazione/disallocazione ci sono, credo che possiamo parlare di istanza.
Tutto questo a priori dei pro/contro, naturalmente.
13/01/2005 12:03 | Raffaele Rialdi
Gravatar

# re: Singleton senza static (o shared se preferite)

Raffaele, mi risulta che nessuna delle implementazioni che hai dato della singleton sia consigliabile... In particolare, l'ultima non è assolutamente thread-safe, anzi, non è difficile trovarsi con un paio di istanze della classe se implementata in questo modo. Consiglio il link postato da Luca Mauri.
25/04/2006 19:47 | Simone Busoli
Gravatar

# re: Singleton senza static (o shared se preferite)

Ammetto la mia ignoranza relativamente ad ATL perchè non so di cosa si tratti, non avendo a che fare con C++.

Ad ogni modo, il problema dell'implementazione della singleton come l'hai fatta tu è che semplicemente non è una singleton - e non che non sia la migliore universalmente - poiché non è per niente improbabile trovarsi con due istanze della classe. Se non fosse poi che cercando su Google per "singleton c#" questo post è il secondo risultato trovato non sarebbe nemmeno un problema così grosso!... però potresti avere sulla coscienza molti sviluppatori licenziati :)

Inoltre, non ho capito a cosa ti riferisci quando parli dell'influenza che hanno "i controlli per renderla thread safe". Se parli del doppio check o dei locking saprai che questa è solo una delle possibilità, poichè utilizzando una variabile "static readonly" in C# il problema è risolto e l'implementazione è semplice semplice.
26/04/2006 00:53 | Simone Busoli
Gravatar

# re: Singleton senza static (o shared se preferite)

Ciao Simone. Credevo di aver già spiegato cosa intendessi nei commenti trascorsi con Adrian. Mi spiace se il discorso è stato confuso.
Tecnicamente parlando neppure l'implementazione del link di Luca è un vero singleton, ma per questo aprirò un nuovo post nel blog.

Per quanto riguarda il discorso di ATL, le stesse cose valgono anche per l'implementazione managed. In sostanza la realizzazione thread safe aggiunge del codice che si rivela ovviamente inutile se utilizzato in un contesto di mono-thread. Questo codice supplementare toglie performance (ovviamente questione tangibile solo in condizioni particolari).

Per questo motivo implementare sempre un singleton thread-safe non è necessariamente una buona scelta e per questo non sono daccordo quindi con i remark "Bad code" citato nel link di Luca.
26/04/2006 20:30 | Raffaele Rialdi
Gravatar

# re: Singleton senza static (o shared se preferite)

Probabilmente mi è sfuggito qualcosa allora, non ho colto cosa intendessi parlando delle prestazioni.

A me sembra che l'implementazione che ha fornito Adrian sia decisamente valida, in quanto priva di qualsiasi controllo che possa pregiudicarne le prestazioni, e thread safe:

public sealed class Singleton
{
private Singleton(){}
public static readonly Singleton Instance = new Singleton();
}

Se poi parliamo di lazy-load, anche questo argomento è stato trattato nell'articolo suggerito da Luca Mauri, ed infatti l'autore, nella sua implementazione, inserisce anche un costruttore statico.
27/04/2006 04:23 | Simone Busoli
Gravatar

# re: Singleton senza static (o shared se preferite)

Visto che nel tuo primo commento parlavi di thread safety, ci ho tenuto a sottolineare che non necessariamente è una buona scelta proteggere tutti i singleton dall'accesso concorrente.
Ho appena fatto un nuovo post nel mio blog che spiega meglio questo concetto.
Si, la proposta di Adrian è valida se non ti interessa il lazy load, come tu già hai detto, e sempre che non usi quell'oggetto in più appdomain, altrimenti quell'implementazione è fallace, così come anche le altre implementazioni citate a quel link di Luca. Di questo parlo proprio nel mio ultimo post.
Lo spirito di questo post voleva essere quello di confrontare la classe statica versus l'implementazione 'classica' del singleton. Non volevo dare una implementazione da usare universalmente in quanto non esiste... di caso in caso bisogna valutare il contesto in cui deve essere usata.
Ti ringrazio di aver puntualizzato con i tuoi commenti perché evidentemente il concetto non era affatto chiaro e spero di averlo chiarito nell'ultimo post di oggi.
27/04/2006 04:45 | Raffaele Rialdi
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET