|
C# versus Java |
Combien de fois n'a t-on pas entendu les questions ou réflexions suivantes : "mais qu'est-ce que ça fait de plus que Java, ce C# ? " ou encore "C# ? Ah bah oui, c'est le Java propriétaire de Microsoft pour contrer Sun" et combien de fois n'avez vous pas eu envie d'expliquer ou de convaincre à ces personnes, au demeurant de bonne foi, que C# méritait plus d'estime car il possédait de multiples facettes et qualités souvent trop longues à énumérer ou à résumer au détour d'un forum de discussions. D'ailleurs, dans la majeure partie des cas, ce dédain face à un nouveau langage, qui plus est développé par Microsoft (quel sacrilège ;-)), n'est qu'un moyen de dissimuler une certaine forme d'ignorance.
Cet article intitulé "C# versus Java" se propose de vous faire connaître C# à travers un ensemble de caractéristiques communes ou différentes de Java (Exceptions, Héritages, ...) avec un regard serein et objectif. Devant la multitude de sujets proposés, nous avons essayé de regrouper les fonctionnalités qui présentaient des similitudes, celles qui différaient de part leur implémentation et enfin, celles qui avaient un caractère novateur.
La plupart des exemples ont été testés avec Microsoft .NET Framework beta 2 et Java 2 Standard Edition.
L'auteur de l'article original est Dare Obasanjo qui a eu la gentillesse de nous autoriser à enrichir et à traduire ses écrits. Certaines parties ont été totalement revisitées par nos soins pour plus de clarté et de simplicité mais en aucun cas le sens et la teneur de l'article original n'ont été modifiés. Nous espérons qu'après avoir lu ces quelques pages vous serez plus à même de comprendre ce qu'est C#, mais aussi d'analyser ou de mieux juger par vous même ses multiples caractéristiques et fonctionnalités.
Index Rapide
Comme Java, C# possède une
super classe, mère de tous les objets : System.Object.
La classe équivalent s'appelle java.lang.object.
Les méthodes présentent dans ces deux classes sont très similaires (ex:
toString()) excepté wait(), notify() et les autres méthodes liées à la
synchronisation.
NOTE: En C#, une classe de type objet peut soit être écrite sous la forme "object" en minuscule ou "Object". En fait, à la compilation ces deux types sont remplacés par System.Object.
Il y a énormément de similitudes entre les deux langages, presque tous les mots-clés Java ont un équivalent en C# à part quelques exceptions telles que transient, throws et strictfp. La table ci-dessous vous illustre les mots-clés présents des deux cotés
|
mot-clé C# |
mot-clé Java |
mot-clé C# |
mot-clé Java |
mot-clé C# |
mot-clé Java |
mot-clé C# |
mot-clé Java |
|
abstract |
abstract |
explicit |
N/A |
object |
N/A |
this |
this |
|
as |
N/A |
extern |
native |
operator |
N/A |
throw |
throw |
|
base |
super |
finally |
finally |
out |
N/A |
true |
true |
|
bool |
boolean |
fixed |
N/A |
override |
N/A |
try |
try |
|
break |
break |
float |
float |
params |
N/A |
typeof |
N/A |
|
byte |
N/A |
for |
for |
private |
private |
uint |
N/A |
|
case |
case |
foreach |
N/A |
protected |
N/A |
ulong |
N/A |
|
catch |
catch |
get |
N/A |
public |
public |
unchecked |
N/A |
|
char |
char |
goto |
goto1 |
readonly |
N/A |
unsafe |
N/A |
|
checked |
N/A |
if |
if |
ref |
N/A |
ushort |
N/A |
|
class |
class |
implicit |
N/A |
return |
return |
using |
import |
|
const |
const1 |
in |
N/A |
sbyte |
byte |
value |
N/A |
|
continue |
continue |
int |
int |
sealed |
final |
virtual |
N/A |
|
decimal |
N/A |
interface |
interface |
set |
N/A |
void |
void |
|
default |
default |
internal |
protected |
short |
short |
while |
while |
|
delegate |
N/A |
is |
instanceof |
sizeof |
N/A |
: |
extends |
|
do |
do |
lock |
synchronized |
stackalloc |
N/A |
: |
implements |
|
double |
double |
long |
long |
static |
static |
N/A |
strictfp |
|
else |
else |
namespace |
package |
string |
N/A |
N/A |
throws |
|
enum |
N/A |
new |
new |
struct |
N/A |
N/A |
transient |
|
event |
N/A |
null |
null |
switch |
switch |
N/A |
volatile |
De la même manière que Java est compilé en byte-code et s'exécute dans un environnement d'exécution managé (Machine Virtuelle JVM), C# est compilé en MSIL s'exécutant dans la CRL (Common Langage Runtime). Les deux plate-formes supportent la compilation Just In Time (JIT). Toutefois, il existe une légère différence entre les deux plate-formes, les compilateurs Java permettent de désactiver totalement le JIT en fonctionnant uniquement en mode interprété alors que les compilateurs .NET en général intègre nativement le JIT. Enfin, il existe des deux cotés la possibilité de pré-compiler en code natif le source. .
Tous les objets Java sont créés sur le tas en utilisant le mot-clé new. Il en va de même pour la plupart des objets C# n'étant pas des types de valeurs (ValueType).
Le ramasse miettes en C# implémente un algorithme bien connu appelé Mark and Compact garbage collection algorithm.
Dans les langages tels que C ou C++, la dimension de chaque sous tableau doit être identique dans les tableaux à plusieurs dimensions. En Java et C#, les tableaux n'ont pas à se plier à cette contrainte car ils peuvent être créés comme des tableaux à une dimension référençant d'autres tableaux. Ils sont appelés "Jagged Arrays". Pour cette raison, les tailles initiales des lignes et colonnes de ce type de tableaux peuvent-être différentes. C'est ce que montre le code suivant :
int [][]myArray = new int[2][];
myArray[0] = new int[3];
myArray[1] = new int[9];
Le code précédent est valide pour Java et C#.
Comme en Java et contrairement à C++, les méthodes en C# doivent être intégrées dans une classe.
C#, comme Java, supporte le concept d'interface qui est assimilé à une classe abstraite pure. De la même façon, C# et Java autorisent l'héritage multiple d'interface et simple d'implémentation.
C# possède une classe System.String qui est équivalente à java.lang.String. Les deux classes sont "immuables", c'est à dire qu'une fois les objets créés, il n'est pas possible de modifier leur valeur. Ceci dans le but de protéger le mécanisme d'encapsulation ô combien fondamental.
C# Code
string csString = "Apple Jack";
csString.ToLower(); /* Does
not modify string, instead returns lower case copy of string */
Java Code
String jString = "Grapes";
jString.toLowerCase(); /*
Does not modify string, instead returns lower case copy of string */
Pour créer une chaîne de caractères autorisant la modification avec la même référence, il est conseillé d'utiliser les classes System.Text.StringBuilder pour C# et java.lang.StringBuffer pour Java.
NOTE: En C#, la classe chaîne peut être écrite sous la forme string ou String.
Les deux langages proposent des mécanismes consistant à interdire toute extension d'une classe. Soit par souci d'optimisation, soit par souci de sécurité. Ainsi, il est interdit de les dériver pour redéfinir des méthodes ou simplement réutiliser l'implémentation. En C#, vous utilisez le mot-clé sealed et en Java le mot-clé final.
C# Code
sealed class Student
{
string fname;
string lname;
int uid;
void
attendClass() {}
}
Java Code
final class Student
{
String
fname;
String
lname;
int uid;
void attendClass() {}
}
Les exceptions en C# et Java partagent énormément de caractéristiques. Les deux langages supportent l'utilisation de l'ordre try pour indiquer qu'un bloc est susceptible de lever une exception et catch pour capturer l'exception en question. De plus, finally est implémenté de la même manière pour spécifier qu'une région de code doit, dans tous les cas être exécutée (exception ou pas). Cela permet de libérer des ressources proprement. Les deux langages proposent une hiérarchie de classes d'Exceptions dérivant d'une super classe : System.Exception pour C# et java.lang.Exception pour Java. Aussi, il est possible de chaîner la levée ou la capture d'exception (throw dans un catch) de part et d'autre. Cela permet, lors de la levée d'une exception, de retourner à l'appelant un type d'exception correspondant à son contexte et à sa couche d'architecture. Par exemple, une ligne non trouvée dans une table se traduira par une SQLException que le développeur prendra soin de renvoyer à l'interface graphique sous la forme d'un ObjectNotFoundException.
NOTE: Cependant, il existe une différence fondamentale entre C# et Java. Le mot-clé throws n'existe pas en C# car vous n'êtes pas contraint de spécifier dans la signature d'une méthode le fait qu'elle est susceptible de lever une exception. Il n'y a, contrairement à Java, aucune vérification de faite à l'exécution.
C# Code
using System;
using System.IO;
class MyException: Exception
{
public MyException(string
message): base(message){ }
public MyException(string
message, Exception innerException):
base(message, innerException){ }
}
public class ExceptionTest
{
static void DoStuff()
{
throw new
FileNotFoundException();
}
public static int Main()
{
try
{
try
{
DoStuff();
return 0; //won't get to execute
}
catch(IOException ioe)
{
/* parent of FileNotFoundException */
throw new
MyException("MyException occured", ioe);
/* rethrow new exception with inner exception specified */
}
}
finally
{
Console.WriteLine("***Finally
block executes even though MyException not caught***");
}
}//Main(string[])
} // ExceptionTest
Java Code
class MyException extends Exception{
public
MyException(String message){ super(message); }
public MyException(String
message, Exception innerException){ super(message, innerException); }
}
public class ExceptionTest {
static void doStuff(){
throw new
ArithmeticException();
}
public static void main(String[]
args) throws Exception{
try{
try{
doStuff();
return; //won't get to
execute
}catch(RuntimeException re){ /*
parent of ArithmeticException */
throw new
MyException("MyException occured", re); /*
rethrow new exception with cause specified */
}
}finally{
System.out.println("***Finally block executes even though
MyException not caught***");
}
}//main(string[])
} // ExceptionTest