Era da un po’ di tempo che mi solleticava l’idea di lanciarmi nello studio di un nuovo linguaggio di programmazione, visto che sono ormai 8 anni e più che programmo esclusivamente in Python. E avendo abbandonato di sana pianta i linguaggi a tipizzazione statica, l’idea era proprio quella di ritornare a studiarne uno.
Complice il talk di Federico di Gregorio al PyCon Due, la mia attenzione è caduta su C#, il linguaggio di elezione per la piattaforma .NET di Microsoft. La scelta è stata effettuata per i seguenti motivi:
- Non è Java e in quanto tale non è molto diffuso
- Non è un linguaggio di ‘basso livello’ in cui ci si deve preoccupare di gestire l’allocazione di variabili, puntatori, ecc
- È sicuramente un linguaggio di ispirazione più moderna
- Non si è necessariamente vincolati alla Microsoft
Quest’ultimo punto è quello che mi ha spinto ad avventurarmi nell’impresa: nonostante C# sia un linguaggio di casa Microsoft, è stato standardizzato (fino alla versione 2.0, ma è in corso di standardizzazione la 3.0) dalla ECMA, e grazie al progetto Mono è possibile sviluppare e distribuire applicazioni C# (attenzione, ho detto C# e non .NET) su qualunque piattaforma (Linux, Win, Mac, UNIX). In realtà conoscevo già il progetto Mono, e in passato aveva provato a darci uno sguardo. Fino a 2 anni fa poteva considerarsi poco più di un progetto sperimentale a vita (una sorta di Wine), ma di recente grazie al contributo di Novell si può considerare una piattaforma Open completa ed affidabile, che sta in tempi brevi supportando anche le versioni 3.0 e 3.5 di .NET.
Quindi, secondo me, l’abbinata C# + Mono può essere considerata una valida alternativa per lo sviluppo di applicazioni multipiattaforma.
Ma veniamo al C#. Beh, devo dire che ritornare dopo anni a pensare ‘statico’ è stato uno shock, molto ma molto più forte del processo inverso, ossia abituarsi alla tipizzazione dinamica venendo da quella statica. La tipizzazione dinamica porta a pensare in termini di funzionalità e di interfacce di oggetto (cosa ancor più vera in Python che ha potenti funzionalità di introspezione), a concentrarsi sulla struttura del programma e non sulla coerenza di tipi e variabili e a generare codice molto ‘prolisso’ e dispersivo. Insomma, il duck typing spinge il programmatore a scrollarsi dalle frustrazioni tipiche che si hanno quando si programma con linguaggi più tradizionali. E a dirla tutta, ho la sensazione che la tipizzazione statica sia la preistoria dell’informatica (e dell’ingegneria del software stessa), e che forse Microsoft poteva osare un po’ di più nel proporre un linguaggio nuovo. Ma ammetto che in genere questo tema divide non poco i programmatori.
Mettendo per un attimo da parte la tipizzazione, cosa c’è in C# che può accumunarlo al Python, o magari renderlo ancora più distante? Secondo Federico, addirittura a tratti C# è un Python con le parentesi graffe. Sarà così?
Queste sono una serie di conclusioni a cui sono giunto dopo i primi 10 capitoli di questo libro della O’Reilly:
- quasi 100 keyword: troppe. Punto.
- le parentesi graffe se le potevano risparmiare: non se ne può più! Sono 35 anni che ci ritroviamo queste maledette {} d’avanti, e veramente è troppo. Innanzitutto, il codice sorgente diventa estremamente lungo e farraginoso, quando con il ‘:’ di Python si riesce a rendere tutto molto più compatto e pulito
public void myFunc(int param) {
if (param > 1) {
Console.WriteLine(i);
}
}quando, invece, in Python basta scrivere:
def myFunc(param):
if param > 1:
print paramPoi, a me sta venendo il tunnel carpale per digitare la combinazione Altgr+Shift+[
- datemi la print: si è vero, anche Python 3.0 avrà la sua brava funzione print() al posto di una keyword, ma print() è infinitamente più breve di Console.WriteLine()
- ok agli shared references: anche C# implementa il modello degli shared references come Python. In parole povere, una variabile C# è una terna del tipo (nome, tipo, riferimento), e i tipi primitivi generano oggetti immutabili. Quindi l'operazione di assegnamento implica far condividere a due nomi lo stesso riferimento ad un oggetto. L'unica differenza con Python è che il passaggio di parametri può avvenire anche nella modalità 'ref', dove ad essere passata come parametro non è il solo riferimento ma tutta la varabile (poi, voglio capire perché tutte le guide e i manuali che ho letto hanno un'abilità tale a complicare l'argomento che difficilmente si riesce a comprendere che il concetto che c'è sotto è molto semplice).
- non bastavano protected, private e public: C# supporta i tipici modificatori di accesso del filone C++ (in realtà manca friend), ma ne introduce di nuovi come internal (accessibile dalle classi dello stesso assembly - una sort di friend con scope a visibilità di modulo), ma anche override per indicare che una sottoclasse sta effettuando l'overriding di un metodo. Se non si è capito, faccio parte di quelli che sono convinti che impiegare 10 giorni per decidere se una metodo o un attributo devono essere private, internal o public è solo una perdita di tempo e un offesa all'intelligenza dei programmatori.
- polimorfismo ed ereditarietà controllata: C#, sulla falsa riga di C++, permette di controllare il polimorfismo con l'uso del modificatore virtual, ma anche con override per indicare espressamente che un metodo effettua l'overriding di un altro. Anche l'ereditarietà può essere controllata e anche impedita per mezzo della keyword sealed (l'equivalente del final Java). Tutti i tipi primitivi la usano, e quindi non si può derivare, ad esempio, dal tipo String, cosa che al contrario in Python è possibile da un bel po' di tempo (versione 2.2), ma è anche vero che le stringhe C# supportano in maniera nativa Unicode, cosa che in Python non avverrà prima della versione 3 con l'unificazione di oggetti str e unicode. 1-1 e palla al centro.
- interessante l'implementazione del costrutto di interfaccia: C# implementa il costrutto di interfaccia. Ora, non c'è molto da meravigliarsi dato che siamo in presenza di un linguaggio moderno a tipizzazione statica, però lo fa in maniera molto interessante. Infatti, è possibile estendere interfacce (creare interfacce che ereditano da altre interfacce), è possibile definire polimorfismo a livello di interfaccia, è possibile definire vincoli sui tipi dei 'generics' in base ad un'interfaccia prestabilita (con la keyword where), esporre selettivamente i metodi di un interfaccia.
- generics, servono: mancavano nelle prime versioni di C#, ci sono dal 2.0. In un linguaggio a tipizzazione statica, se se ne abbraccia il credo, servono. Interessante la possibilità di poter definire vincoli sull'interfaccia del tipo generico T.
- direttamente da Python, i generatori: pardon, gli enumeratori. Esattamente lo stesso concetto presente in Python (stessa keyword yield), ma basati su un'interfaccia specifica IEnumerable<T>. Inutile dire che sono utilissimi.
- dizionari con keyword arbitrarie: il tipo Dictionary<K,V> (che non è primitivo come in Python) consente di specificare tipi arbitrari per le chiavi, e non solo oggetti immutabili come in Python, a patto che tale oggetto non cambi nel flusso di esecuzione.
- possibilità di specificare funzioni di conversioni tra tipi: questa è una funzionalità che reputo sublime. A differenza di quanto si legge in giro, C# è un linguaggio fortemente tipato e quindi non c'è il concetto di cast presente nel C (che è debolmente tipato). Quello che viene chiamato erroneamente cast, è la possibilità del C# di specificare le funzioni di conversione dei tipi, sia implicite sia esplicite. Ad esempio:
public static implicit operator MyType(int i) {
//Qui il codice di conversione da intero
}
public static explicit operator int(MyType t) {
//Qui il codice di conversione verso intero
}
...
public static void Main(string[] args) {
MyType t = 10; //Usa la conversione implicita
int a = (int)t; //Usa la conversione esplicita
}
Queste sono le prime osservazioni che riesco a fare su C#. Man mano che andrò avanti nello studio del linguaggio e del framework Mono posterò nuovi articoli. Nel frattempo, come sempre, sono apprezzati commenti ed osservazioni.

Se volevi imparare un linguaggio a tipizzazione statica facevi
meglio a studiarne uno con type inference, tipo SML o Haskell; C# pare proprio una pizza per un Pythonista.
Beh si, è vero che è una pizza (è incredibile quanto siano prolissi e dispersivi i programmi scritti con C#), però è anche vero che se tu vuoi un linguaggio da adoperare in un ambiente di produzione, quelli che mi hai citato dubito che vadano bene. E poi ammetto che non riesco a digerire i linguaggi funzionali, è più forte di me.
Io uso quasi sempre Delphi, ma capisco che purtroppo, soprattutto per problemi commerciali, è un linguaggio condannato ad un’inesorabile declino. Per questo sto valutando la possibilità di iniziare ad utilizzare un nuovo linguaggio; C# è uno di quelli che stò valutando.Ho trovato interessanti le tue osservazioni che mi hanno mostrato come C# abbia ereditato molte caratteristiche da Delphi. E non è un caso, visto che lo sviluppo, sia di .NET che di C#, sono diretti da Anders Hejlsberg che, in Borland, ha sviluppato sia turboPascal che Delphi.Anch’io provo un certo senso di orticaria alla vista di quel marasma di {}, però di qualche cosa bisogna pur morire!! D’altronde non si può nemmeno dire che i Begin/end del Pascal siano particolarmente gustosi!Nel C# apprezzo l’approccio "fai quel che vuoi ma voglio essere sicuro che lo fai volendolo fare" che è alla base di casting esplicito, virtual/override dichiarato….che èalla base anche di Delphi. E lo apprezzo perchè con Delphi ho sperimentato che previene un sacco di possibili errori subdoli.Questa similitudine sintattica e funzionale con Delphi mi renderebbe più semplice la migrazione, anche se al momento non so valutare se C# è destinato a diventare un linguaggio duraturo e di punta; non vorrei scoprire di aver impiegato energie per passare da un linguaggio di nicchia ad un’altro linguaggio di nicchia. Cosa ne pensi del futuro di .NET e di C#?
Scommettere sulla longevità di una piattaforma e di un linguaggio è sempre un azzardo non di poco conto, soprattutto nel medio/lungo periodo. Non ne parliamo poi se di mezzo c’è la Microsoft, che ci ha abituato molto spesso a cambiamenti anche pesanti dall’oggi al domani. Mi ricordo ancora bene il filone del COM/COM+ sviluppatosi sul finire degli anni ’90 e gli inizi del 2000: sembrava la soluzione definitiva e soprattutto destinata a durare anni. Poi d’improvviso arrivò .NET, spazzando via tutto (con qualche dubbio di troppo, IMHO).
Quanto .NET sia una piattaforma valida, questo secondo me è un punto molto delicato. C’ho giocato per un pochino, e ho realizzato dei piccoli programmi che ci servivano per garantire della compatibilità verso applicazioni Windows. Io credo che sia una piattaforma valida ed interessante ma incompleta. Incompleta perché un arsenale di quella portata relegata esclusivamente al settore Windows è troppo limitante. Si c’è Mono, però alla fine se si cerca la stabilità di sviluppo e la piena compatibilità, allora perché non scegliere Java? Per qualche feature in meno del linguaggio? Dubito che questo possa essere solo una valida ragione per adottare C#/.NET. D’altro canto, oggi come oggi i framework si assomigliano un po’ tutti, e secondo me un linguaggio si sceglie rispetto ad un altro solo su scelte radicali: ad esempio, scelgo Python o C#, ma dire scelgo C# o VisualBasic.NET o anche Java mi sa di ideologico.
Vivrà nel lungo periodo C#? Secondo l’indice TIOBE C# non è al momento un linguaggio "killer", e da quel che si vede in giro (soprattutto in Italia) è così. Oggi il mercato dei linguaggi è abbastanza polarizzato sulle applicazioni finali: web o resto del mondo. E la maggiore vivacità sta proprio nel settore web, dove è vero che la fa da padrone PHP, però altri linguaggi rosicchiano fette di mercato, e soprattutto questo è il segmento dove è più facile oggi introdurre innovazione.
Questo per dire che secondo me nel medio/lungo periodo le cose resteranno così come sono, e quindi è un investimento che si può fare. D’altro canto io sono sempre stato convinto che sono meglio le nicchie: si lavora più tranquilli e ci si riesce a ricavare le proprie autonomie. Quindi, dovendo limitare l’ambito a Windows, la mia risposta è sicuramente sì.