Classi statiche & generics: un comportamento da tener presente!
Date un’occhiata alla seguente classica statica:
1 public static class DataProvider<T> where T : new() 2 { 3 private static bool init; 4 5 static void initialize() 6 { 7 init = true; 8 } 9 10 public static void MakeSomeOperation() 11 { 12 if (!init) initialize(); 13 } 14 }
Estratto da un data provider che ho sviluppato tempo fa.
E’ una classe statica DataProvider che fa uso di un generics <T>. Ha una proprietà statica booleana Init, che utilizza un field privato init. L’unico metodo presente è MakeSomeOperation(), statico anch’esso, che prima di fare qualcosa controlla se la classe è già stata inizializzata. Nulla di strano, giusto?
La morale però è questa: la prima volta che utilizzo questa classe chiamando il metodo pubblico MakeSomeOperation(), entro nel piccolo blocco if e quindi viene eseguita la initialize() privata. Poi init viene impostata a true, per cui pensavo stupidamente di non passare più dalla procedura di inizializzazione. Cosa che non è affatto vera. Per esempio, con il codice seguente…
DataProvider<ArrayList>.MakeSomeOperation(); DataProvider<ArrayList>.MakeSomeOperation(); DataProvider<StringBuilder>.MakeSomeOperation();
…utilizzo tre volte la classe DataProvider. Le prime due chiamate usano T come se fosse un ArrayList; la terza ed ultima chiamata usa T come se fosse uno StringBuilder. Ho dovuto usare due classi con il costruttore vuoto, dato il constraint applicato al generics.
Alla prima chiamata (ArrayList) avviene l’inizializzazione.
Alla seconda chiamata (ArrayList) l’inizializzazione non avviene più.
Alla terza chiamata (StringBuilder) l’inizializzazione viene eseguita ancora una volta.
Ogni volta che cambio il Type assunto da T, la classe statica DataProvider viene reistanziata per quel particolare tipo, e quindi viene nuovamente scatenata l’esecuzione di initialize(). Ci sarebbe un modo per evitarlo, cioè spostare la definizione del generics dal nome della classe al nome del metodo. Però, ovviamente, dipende da quello che dobbiamo fare, mica è detto che debba per forza sempre essere così!
Technorati Tags: programming .NET