Come
spesso succede, prima che un prodotto veda la luce, la potente macchina
marketing dell’azienda che lo sviluppa si mette in moto per promuoverlo
o per iniziare a far parlare del prodotto, prima che sia pronto. Per questa
ragione escono libri, interviste, articoli di vario genere, gruppi di discussione,
siti e preview.
Circa
un anno fa il marketing di Microsoft si è messo in moto per C#,
da leggere C sharp, che molti di voi sicuramente hanno gia avuto modo di
incrociare lungo la rete.
C#
non è altro che il linguaggio che andrà a sostituire Java
nella prossima versione di Visual Studio, che nasce pensato per poter essere
il linguaggio principale per lo sviluppo di applicazioni all’interno del
framework .NET.
L’abbandono
di Java libera Microsoft dai problemi nei confronti di SUN. Primo fra tutti
il vincolo di non poter ampliare un linguaggio come Java e di non poter
rendere attive di default le proprie estensioni.
Inoltre
permette a Microsoft di riutilizzare gran parte del pensiero che si trova
alle basi di Java all’interno di un nuovo linguaggio, nato per essere allo
stesso tempo object oriented e semplice da usare e per poter sfruttare
sin dal principio l’immensa collezione di librerie scritte per Windows.
Perché
C#
I
linguaggi maggiormente utilizzati in ambiente Windows sono sicuramente
Visual Basic e Visual C++, almeno per quello che riguarda Microsoft. Col
passare del tempo i nuovi sviluppi tecnologici hanno obbligato Visual C++,
e in modo più pesante Visual Basic, ad imbottirsi di nuovi costrutti,
librerie e wizard, in modo da riuscire a creare tutto quello che in sistema
operativo come Windows permetteva di fare.
Col
tempo quest’approccio ha modificato questi linguaggi che dovevano però
rimanere, nel limite del possibile, retrocompatibili.
Perché
allora non creare un nuovo linguaggio che potesse sfruttare la semplicità
di Java, libero da ogni vincolo col passato e che pronto ad utilizzare
il framework di oggetti gia disponibile in ambiente Windows? Inoltre perché
non pensarlo in modo da essere portabile fra processori di generazioni
diverse, rendendo semplice, ad esempio, il passaggio di architettura da
32 a 64 bit?
Microsoft
diede allora a Anders Hejlsberg, per chi non lo ricorda la mente dalla
quale nacquero Turbo Pascal e Delphi, il compito di studiare un “qualcosa”
che potesse dare una valida risposta a queste esigenze. Da questo lavoro
nacque C#.
Le
caratteristiche di C# sono:
-
Semplicità
di utilizzo. Come Java, si è semplificato lo sviluppo di codice
evitando le dichiarazioni forzate di funzioni, come accade in C e C++.
Si sono rimossi i legami con i processori e sono state introdotte delle
funzionalità per riuscire a scrivere in maniera semplice applicazioni
Internet Based e Multithread Oriented.
-
Integrazione
diretta con COM (Component Object Model). Per riuscire a scrivere ed utilizzare
oggetti COM in maniera semplice ed intuitiva, sono stati introdotti una
serie di costrutti nel linguaggio ed una serie di classi che rendessero
semplice il dialogo fra C# e COM.
-
Integrazione
con l’ambiente .NET. C# si propone come lo strumento di sviluppo del nuovo
ambiente .NET di Microsoft. Questo si capisce dalla notevole mole di codice
C# presente in tutti gli esempi di utilizzo del framework esistenti al
momento.
Queste
sono solo alcune delle caratteristiche di C#, ma probabilmente le principali.
Inoltre sono quelle che dovrebbero motivare un programmatore a sceglierlo
come linguaggio di sviluppo.
In
sintesi: “lavori o vuoi lavorare con .NET? Allora C# è la scelta
migliore”.
Vediamo
ora quali sono invece i punti di forza di Java e perché si dovrebbe
scegliere questo linguaggio.
Perchè
Java
Da
programmatore Java mi sembra perifno inutile scrivere le motivazioni
che spingono ad utilizzarlo come linguaggio. Sono sicuramente molteplici,
ma le maggiori sono date da:
-
Semplicità
d’uso. Sono stati abbattuti molti vincoli rispetto a linguaggi come C++,
che permettono la scrittura di codice lineare e potente.
-
Nella
definizione di linguaggio sono già presenti le specifiche per l’utilizzo
di database SQL. Questo fatto non obbliga a nessun particolare artificio
per utilizzare un programma Java, a parità di JDK, in una piattaforma
piuttosto che un'altra. La stessa operazione in altri linguaggi si rivela
molto costosa a livello implementativo.
-
Definizione
di Socket e Thread a livello di linguaggio. Java nasce pensato per Internet,
dove il protocollo utilizzato è TCP/IP. Il fatto di avere, nel framework
di classi base, la classe Socket ci permette di scrivere applicazioni Internet
supportate da tutte le piattaforme che implementano Java. Altri linguaggi,
come C, non hanno tale implementazione a livello di framework base e quindi
obbligano ad avere implementazioni diverse da sistema operativo a sistema
operativo. Stesso discorso per i Thread indispensabili per qualsiasi applicazione
che fornisca servizi all’interno di una rete.
-
Portabilità.
Mi è capitato più volte di scrivere programmi che dovevano
essere utilizzati in piattaforme diverse da quella di sviluppo. Pur utilizzando
Windows come ambiente di sviluppo primario e AIX come target, sistemi operativi
completamente diversi, non ho mai avuto problemi nel passaggio di applicazioni
da un sistema all’altro. Tutto questo grazie all’architettura di questo
linguaggio, sicuramente ben definita.
Le
motivazioni che possono spingere ad utilizzare Java sono molto maggiori,
ma credo possano variare da applicazione ad applicazione, mentre queste
poche possono sicuramente proporsi come le più sentite.
Convergenza o
divergenza?
Come
abbiamo visto, entrambi i linguaggi aspirano alla semplicità. Le
complessità delle moderne applicazioni rischiavano di far diventare
i vecchi linguaggi di programmazione troppo complessi da utilizzare, per
la stesura delle applicazioni che oggi si è costretti a scrivere.
Ognuno
dei due però si distingue per il target che vuole colpire. C# vuole
essere il linguaggio primario di .NET e Java il linguaggio primario di
Internet.
A
questo punto vediamo di entrare maggiormente in dettaglio nel codice per
capire cosa differenzia C# da Java.
|
Figura
1: Il debugger di C#
Confronto
Per
una corretta analisi delle funzionalità dei due linguaggi, cominciano
col confrontare il programma più piccolo che si può fare
con Java e con C#, cioè il classico ”Hello World”.
Ecco
di seguito le due implementazioni. Per quello che riguarda Java:
public
class test {
public static void main(String[] args) {
System.out.println("Ciao Mondo");
}
}
per
quello che riguarda C#:
class
test {
static void Main(string[] args) {
System.Console.WriteLine("Ciao Mondo");
}
}
Come
si può notare la struttura è molto simile. In entrambi i
casi si tratta di una classe principale con un metodo predefinito statico
che prende come argomento un array di stringhe.
In
entrambi i casi è poi possibile accedere direttamente all’oggetto
System ed utilizzare lo standard output per stampare una riga.
Molto
simile è anche la dichiarazione di una classe esterna, che in Java
viene fatta tramite il comando import e in C# tramite il comando using:
//
Java
import
java.lang.System;
//
C#
using
System;
|
Figura
2: I parametri di compilazione di C#
Statement
Derivando
entrambi da C, non ci sono molte differenze negli statement utilizzabili
in questi due linguaggi. Ad esempio è identico l’utilizzo di:
- if/then/else
-
switch
-
while
-
do while
-
break/continue
-
return
-
new
L’unica
differenza è data dal fatto che C# introduce un costrutto nuovo
che è foreach.
Foreach
serve per accelerare la scansione di un array, evitando di scrivere il
codice che legge un singolo valore. Ad esempio il seguente codice Java:
//
Assumendo che vector sia un oggetto della
//
classe java.util.Vector
int
tot = 0;
for
(int nCur = 0; nCur < vector.size(); nCur++) {
// Viene preso l’elemento ennesimo
int i = (Integer)vector.elementAt(nCur);
// E il suo valore viene aggiunto al totale
tot += i;
}
In
C# invece si sarebbe potuto scrivere:
//
Assumendo che vector sia un oggetto della
//
classe
ArrayList
int
tot = 0;
foreach
(int i in vector) {
// aggiungo il valore al totale
tot += i;
}
|
Figura
3: L’uso delle property
Eccezioni
Altro
particolare interessante è dato dall’opzionalità del costrutto
try/catch/finally.
Se
in Java volessi, con una catch, gestire tutte le eccezioni di una certo
blocco di codice, dovrei scrivere qualcosa di molto simile a questo:
try{
// Codice
}
catch (Throwable e){
// Gestione delle eccezioni
}
questo
perché il ramo di catch, in un try, è obbligatorio.
In
C# non è obbligatorio, ed è possibile scrivere tranquillamente:
try{
// Codice
}
catch {
// Gestione delle eccezioni
}
omettendo
di specificare quale oggetto deve gestire la catch. Inoltre è anche
possibile omettere completamente la parte di catch, l’importante è
definire almeno la clausola finally.
Definizione
delle classi e sincronizzazioni
Anche
in questo caso ci sono delle differenze nella definizione, ma sono relative
soprattutto al modo col quale debbono essere scritte le varie modalità
di ereditarietà. Ad esempio i costrutti Java:
class
A extends B {
// implementazione
}
interface
IA extends IB {
// implementazione
}
class
C implements IA, IB {
// implementazione
}
Vengono
implementati in C# allo stesso modo di C++:
class
A : B {
// Implementazione
}
interface
IA : IB {
// Definizione
}
class
C: IA, IB {
// Implementazione
}
quindi
non viene definita una keyword diversa per estendere od implementare una
classe o un’interfaccia, ma viene genericamente utilizzato il simbolo di
‘:’.
Un'altra
leggera differenza è data anche dalla gestione del costrutto synchronized,
che in C# funziona allo stesso modo, ma è chiamato più semplicemente
lock.
|
Figura
4: L’uso di api
Windows
Estensioni di
C#
Analizziamo
ora alcune delle novità che, un linguaggio nuovo come C#, offre.
Una
gradita sorpresa è data dalle properties, e qui probabilmente un
piccolo influsso da Delphi si inizia a vedere.
Il
costrutto properties permette di definire una variabile distanza pubblica
interrogabile ed assegnabile all’interno di un oggetto, e fino a qui nulla
di particolare. La cosa interessante è data dal poter definire,
in modo esplicito, una funzione che controlla l’assegnazione a tale variabile
ed una che ne controlla la lettura.
Con
Java si può ottenere lo stesso effetto gestendo due funzioni di
set e get. La prima che gestisce l’assegnazione e la seconda che controlla
l’interrogazione.
Per
semplificare il tutto in C# si è optato per il costrutto properties.
Osservate il seguente esempio.
Nella
parte di Main viene definito un oggetto test e viene assegnato, ad una
sua variabile d’istanza numero, il valore 10. Successivamente tale valore
viene preso e visualizzato a video. Proviamo però ad osservare com’è
stata implementata questa variabile all’interno della classe test:
class
test {
static void Main(string[] args) {
test x = new test();
x.numero = 10;
System.Console.WriteLine( "Valore = " +x.numero );
}
private int nNum = 0;
public int numero {
get {
System.Console.WriteLine("Legge valore");
return nNum;
}
set {
System.Console.WriteLine("Scrive valore");
nNum = value;
}
}
}
le
due funzioni get e set permettono di controllare perfettamente l’accesso
a numero.
Anche
se questo costrutto può sembrare superfluo, sicuramente rende molto
più semplice la scrittura di codice. Inoltre permette di intervenire
in quei casi in cui si sia esposta una variabile di istanza la cui gestione
debba essere successivamente controllata.
|
Figura
5: Il debugger visuale
Unificazione fra
tipi primitivi ed oggetti
Un
altro particolare interessante di C# è dato dall’unificazione fra
i tipi base e gli oggetti.
Questo
vuol dire che, ad esempio, non occorre convertire un numero in un oggetto
per averne il corrispettivo String come in Java:
Integer
i = new Integer(1971);
System.out.println(i.toString());
ma
basta applicare il metodo ToString direttamente al numero:
System.Console.WriteLine(1971.ToString());
Questo
vuol dire che tutto in C# è una sottoclasse di object, anche i tipi
base che in Java non lo sono.
Strutture ed enum
Le
strutture erano state volutamente rimosse da Java, ma in C# riappaiono.
L’unica
estensione introdotta è la possibilità di aggiungere costruttori
e metodi.
Diciamo
che la struttura diventa così una piccola classe, col vincolo di
non poter ereditare da un'altra struttura.
Un’altra
importante caratteristica delle strutture è data dal loro utilizzo
per valore e non per riferimento. Questo vuol dire che, in caso di passaggio
di parametri tra metodi, la struttura viene passata interamente sullo stack,
mentre se fosse un oggetto ne sarebbe passato solo il suo riferimento.
Per
quello che riguarda le enum il concetto è identico a quello presente
in C. Vi è la possibilità di definire oggetti con parametri
letterali, facendo gestire in automatico dal compilatore la loro gestione.
Java tende invece a sopprimere questo concetto, utilizzando semplicemente
dei valori numerici di tipo final static ed ottenendo, a tutti gli effetti,
lo stesso meccanismo.
Codice Nativo
C#
nasce anch’esso con l’idea di non produrre del codice nativo per una determinata
piattaforma, ma del codice intermedio. In questo modo è possibile,
e qui Java insegna, portare i programmi scritti in C# su altre piattaforme.
In
realtà esiste una feature che potrebbe dare fastidio a questo porting
automatico. Tale fastidio è dato dalla facilità con la quale
è possibile scrivere del codice che interroga direttamente API Windows
o richiama funzioni C.
Il
concetto è simile a JNI, ma molto più semplice da attuare,
ad esempio per chiamare la funzione MessageBoxA è sufficiente dichiarare
l’utilizzo della dll user32.dll e dichiarare un metodo come extern.
using
System;
class
MyClass
{
[sysimport(dll="user32.dll")]
public static extern int
MessageBoxA(int h, string m, string c, int type);
public static int Main() {
return MessageBoxA(0, "Hello World!", "Caption", 0);
}
}
Per
chi ha utilizzato Java SDK di Microsoft, questa tecnica è praticamente
identica a quella utilizzata nell’implementazione Java di tale prodotto.
In
Java, per poter fare la stessa cosa, occorre scrivere del codice direttamente
in C.
Non
mi sento però di criticare fino in fondo questo approccio.
Da
un lato l’implementazione di Java è corretta. Rendere troppo semplice
l’interfacciamento con codice “non puro” può compromettere il concetto
alla base del linguaggio, che è quello di scrivere un programma
il più portabile possibile.
D’altro
canto è anche vero che, se ci fosse l’esigenza di fare una chiamata
ad una libreria di sistema, obbligare il programmatore a scrivere codice
C, quando si poteva risolvere tutto con dei semplici costrutti, sarebbe
molto più semplice.
Conclusioni
Alla
luce dello sviluppo attuale, la miglior scelta per la scrittura di applicazioni
stabili, non può che ricadere che su Java. È molto potente,
semplice, fruibile e l’ambiente di sviluppo può essere scaricato
gratuitamente dalla rete. Inoltre ha numerose librerie di supporto ed i
maggiori ambienti di sviluppo esistenti lo supportano. Java è un
linguaggio facilmente trasportabile da piattaforma a piattaforma senza
nessuna particolare cura durante la scrittura di codice.
C#
invece risulta ancora troppo giovane come linguaggio di programmazione,
soprattutto perché non esiste ancora una versione 1.0. Inoltre non
si riesce ancora a capire quanto può risultare stabile e quando
potrà essere utilizzato fuori dalla piattaforma .NET.
Non
sarà sempre così. Non appena il linguaggio di stabilizzerà
ed inizieranno ad uscire le prime versioni, sicuramente, sarà uno
dei linguaggi più semplici per la scrittura di applicazioni Windows.
Inoltre, non avendo legami col passato, sarà molto lineare scrivere
applicazioni in C#, con grande gioia dei programmatori, che troveranno
maggiormente facile scrivere un componente in C# piuttosto che in C++ o
Visual Basic.
Gli
esempi descritti in questo articolo possono essere scaricati da qui
Bibliografia
[1]
http://www.microsoft.com. Homepage di Microsoft dove scaricare il preview
di .NET
[2]
http://java.sun.com. sito SUN dal quale scaricare l’ultima versione di
JDK.
[3]
http://windows.oreilly.com/news/seesharp_0700.html. "C# Is Pronounced 'See
Sharp,'" Arthur Griffith (windows.oreilly.com).
[4]
http://www.javaworld.com/javaworld/jw-11-2000/jw-1122-csharp1.html. C#:
A language alternative or just J--?, Part 1.
[5]
http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-csharp2_p.html. C#:
A language alternative or just J--?, Part 2.
[6]
http://www.infomedia.it/artic/Baccan, sito contenente alcuni articoli di
approfondimento degli argomenti trattati.
Matteo
Baccan è uno specialista di progettazione e sviluppo in C++, Java
e Lotus Notes. Attualmente si occupa dello studio di tecniche avanzate
di programmazione in ambito Internet/Intranet tramite Lotus Notes e Java,
presso Integra Italia. Si possono consultare alcune sue pubblicazioni presso
http://www.infomedia.it/artic/Baccan. Può essere contattato tramite
e-mail all'indirizzo mbaccan@mokabyte.it
|