I tipi in C# possono essere:
ClassiVediamo un esempio di classe sealed e di classe static.Supponiamo di avere necessità, in una ipotetica architettura, di dare allo sviluppatore finale la possibilità, tramite API, di estendere il nostro applicativo, supponiamo attraverso ereditarietà di alcune particolari classi.Supponiamo che nella classe SEOSettings vi siano i metodi per renderizzare i meta tag più "consoni", all'interno di una web page. Lo sviluppatore finale, potrà estendere la classe SEOSettings, e sostituirne l'implementazione precedente.Ma supponiamo ora non ci venga voglia di estendere la classe SiteRender (marcata sealed), per ottenere un render customizzato dell'intero sito web. Sul manuale del prodotto c'è espressamente scritto che non possiamo estendere quella classe perchè il comportamento finale risulterebbe compromesso.Noi non leggiamo il manuale, perciò noi proviamo con la stragegia di prima e, in compilazione, già siamo fermi. Infatti la parolina chiave sealed ci permette di impedire la estendibilità di una classe, con conseguente impossibilità di ridefinirne i metodi.
Una classe static è, per definizione, una classe non istanziabile. Ma cosa può servire?Intanto ormai oggi, TUTTE le applicazioni hanno una classe stile "Utilities", "Commons" o cose simili, al fine di contenere metodi di utilità globale (spesso già static) invocabili in qualsivoglia contesto della nostra applicazione. Una classe static afferma soltanto di contenere SOLO metodi statici, evitando che il programmatore possa crearne istanze.
Funzioni e passaggi ref e outUn concetto molto familiare per i developer più vecchiotti, è sicuramente il passaggio parametri by-reference. Un codice di questo tipo:
void MethodA() { int a = 2; int b = 3; Swap(ref a, ref b); Console.WriteLine(a.ToString() + " - " + b.ToString()); } void Swap(ref int a, ref int b) { int tmp = b; b = a; a = tmp; }
CostruttoriLe difficoltà maggiori riguardo ai costruttori si hanno in seguito all'ereditarietà. Li vedremo più in là; per ora, da ricordare, ci sono i costruttori static che sono preposti per l'inizializzazione di tutto ciò che è appunto statico, all'interno della nostra classe. Supponiamo di avere una classe in cui è presente un dizionario di delegate, interrogabile staticamente da ogni classe del progetto.Questo dizionario dovrà essere opportunamente compilato PRIMA che venga utilizzato da qualsiasi metodo esterno. La soluzione potrebbe essere una cosa simile:
private static Dictionary<string, Func<int, int, int>> dict = new Dictionary<string, Func<int, int, int>>(); static Utils(){ dict.Add("SUM", (a, b) => { return a + b; }); dict.Add("SUB", (a, b) => { return a - b; }); dict.Add("MUL", (a, b) => { return a * b; }); } public static Delegate GetFunction(string key) { return dict[key]; }
static void Main(string[] args) { Console.WriteLine(Utils.GetFunction("SUM").DynamicInvoke(10, 20)); Console.Read(); }
Se abbiamo qualche risorsa da distruggere, connessioni da chiudere e/o operazioni "finali", è consigliato utilizzare un distruttore, oppure il pattern Disposable tramite l'implementazione dell'interfaccia IDisposable.Infatti, se si implementa l'interfaccia e il metodo Dispose, potremmo anche usare il nostro oggetto nel costrutto using, avvalendoci di una distruzione automatica, a fine utilizzo.
using (var s = new DisposableObject()) { //operazioni } using (var s = new UndisposableObject()) { //invalido, l'oggetto non implementa IDisposable }
Proprietà implementate automaticamenteSi spiega da solo: volete implementare una proprietà in associazione 1-1 con un campo privato? Basta questo costrutto:
public int MyProperty { get; set; }
Tipi Enum e Flags EnumI tipi enum sono usati spessissimo per favorire il costrutto switch. Quello che possiamo aggiungere alla knowledge base è che il tipo enum è in realtà un tipo value (in particolare un int) che noi possiamo anche cambiare con un altro tipo value. Dichiarazioni tipo sono:
enum MyEnum:ushort { A, B, C }
Le Flags Enum invece sono quelle enum tanto carine utilizzate spesso per identificare insiemi di attributi di una particolare entità.Si dichiarano così:
[Flags] enum Attrs { IS_LOCKED=0x01, IS_READY = 0x02, IS_NICE = 0x04, IS_MOODY = 0x08, ALL=IS_LOCKED|IS_MOODY|IS_NICE|IS_READY }