Introduction
Digne successeur (selon Microsoft) des langages C/C++, C# est certes
proche de ses prédécesseurs, mais présente
des différences notables qui peuvent représenter des
pièges pour le développeur se jettant directement
dans ce langage. En effet, si la ressemblance entre C++ et C# est
frappante et permet de faciliter la transition d'un langage à
l'autre, un programmeur C++ ne peut pas sauter de l'un à
l'autre en ne connaissant que les syntaxes respectives: bien que
syntaxiquement similaires, ces deux langages présentent de
grandes différences au niveau de leur conception même,
suffisamment pour rendre la transition plus difficile qu'elle ne
paraîtrait au premier abord.
L'exemple sempiternel
présente de première variations:
(fichier helloworld.c)
#include <iostream>
int main() {
std::cout << "Hello, world!\n";
return 0;
}
(fichier helloworld.cs)
using System;
class HelloWorld {
static void Main() {
Console.WriteLine("Hello world!");
}
}
Comme le noterons les programmeurs C/C++, il manque certains éléments:
- Le programme n'utilise pas de méthode globale pour Main.
Les méthodes et variables ne sont pas supportées au
niveau global, mais sont contenus dans des déclarations de
type (classes...).
- Le programme n'utilise aucun opérateur ::
ou -> . ::
n'est pas un opérateur en C#, et l'opérateur <<
n'est utilisé que rarement dans les programes. L'opérateur
. est utilisé pour les noms
composés, comme Console.WriteLine.
- Le programme ne contient pas de "forward declaration".
Elles sont inutiles, étant donné que l'ordre de déclaration
n'est pas pris en compte.
- Le programme n'utilise pas #include pour l'importation. Les dépendances
entre programmes sont gérées de manière symbolique
plutôt que textuelle. Cette approche élimine les barrières
entre les programmes écrits dans différents langages.
Par exemple, la classe Console pourrait être écrite
dans un autre langage.
- pas de ; après la déclaration
de classe.
Ainsi, vous pouvez écrire du code parfaitement légal
en C++, il ne compilerait pas pour autant en C#. Pire, il pourrait
ne pas se comporter de la manière prévue. Nous allons
aborder dans cet article quelques points spécifiques à
C# qui le différencient de C++.
Typage
C# fait une différence entre les types de valeur (value)
et les types de référence (reference). Les
types simples (in, long, double, ...) et les structs sont
des types de valeur, tandis que toutes les classes sont des types
de référence, tout comme les objets, interfaces, tableaux
et chaînes. L'occurence d'un type value représente
la donnée réelle (stockée dans la pile), là
où celle d'un type référence représente
un pointeur ou une référence aux données (enregistrées
sur le segment de mémoire). Pour résumer, un type
valeur en C# correspond à une variable en C++, et un type
référence à un pointeur.
Là où un programmeur C++ doit faire attention, c'est
que C# détermine lui-même les types qui seront représentés
comme valeurs et ceux qui seront représentés comme
références...
Structures
Il y a des différences majeures entre les structs
de chaque langage. En C++, une struct est une forme de classe,
sauf que les héritages et accès sont par défaut
publics plutôt que privés. En C#, les structs
sont bien différentes des classes: elles sont conçues
pour encapsuler de petits objets, et sont de type valeur (pas référence),
donc sont passées par valeur. Elles ont des limitations qui
ne s'appliquent pas aux classes, n'ont pas de construction par défaut
(sans paramètre), et n'ont pas de destructeur.
Le bénéfice est que les structs de C# sont plus efficaces
que les classes pour la création d'objets légers.
Tout est objet
En C#, tout dérive de la classe System.Object, en définitive:
classes, types de valeur... De fait, vous pouvez assigner une valeur
de n'importe quel type à une occurence d'Object. En C++,
les héritages multiples sont permis dans le modèle
objet, ce qui n'est pas le cas en C#: il ne permet qu'un héritage
d'une classe de base, bien qu'une classe C# puisse implémenter
de multiples interfaces.
En C#, il n'y a qu'un seul symbole pour faire référence
à une valeur ou un attribut: le point. Que vous fassiez appel
un attribut, une classe ou un espace de nom, vous utilisez le point
et C# se charge de déterminer comment interpréter
la réference.
La classe Objet offre quelques méthodes
utiles.
Paramètres
En C# comme en C++, une méthode ne peut renvoyer qu'une seule
valeur. En C++, on peut dépasser cette limitation en utilisant
des pointeurs ou références dans les paramètres.
En C#, il faut passer par les affectations définies/assurées
(definite assignments, un "héritage" de
Java), ce qui signifie que les variables locales doivent être
affectées avant d'appeller la méthode. Pour éviter
cela, C# dispose du mot-clé out,
qui indique que l'on peut passer une variable non initialisée,
et elle sera passée par référence.
C++: public void
GetStats(ref int age, ref int ID, ref int yearsServed)
C# : public void GetStats(out int age,
out int ID, out int yearsServed)
New
Le mot-clé new permet en
C++ d'instancier un objet du "tas" (heap). En
C#, avec les types référence, le mot-clé new
fait de même, mais avec les types valeur comme les structs,
l'objet est créé sur la pile (stack) et un
constructeur est appellé.
Propriétés
En C#, les propriétés sont les éléments
premiers d'une classe. Pour le client, elles ressemblent à
des variables, mais pour l'implémenteur de classes, elles
ressemblent à une méthode. Cela permet une encapsulation
totale tout en donnant au client un accès à ses membres.
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
Fred.Age = 17;
Tableaux
C# dispose d'une classe de gestion de tableaux mieux faite que les
tableaux C/C++. Par exemple, il est impossible de sortir des limites
d'un tableau C#. Il y a trois sortes de tableaux C#: unidimensionnel,
multi-dimensionnel et les tableaux de tableaux (jagged arrays).
int[] tableau = new int[5];
ou
int[] tableau = { 2, 4, 6, 8, 10 };
int[,] tableauMulti =
new int[lignes, colonnes];
ou
int[,] tableauMulti =
{
{0,1,2}, {3,4,5}, {6,7,8}, {9,10,11}
};
int[][] jaggedArray =
new int[4][];
puis
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[2];
jaggedArray[2] = new int[3];
jaggedArray[3] = new int[5];
Ce ne sont là que quelques exemples parmi de nombreux autres.
Notre but n'est évidemment pas de dire que le programmeur
C++ serait perdu dans un environnement C#, bien au contraire, mais
qu'il lui faudra s'adapter à l'environnement (en particulier
l'architecture .NET) et à quantité de petites variations
dans la syntaxe, comme nous avons commencé à le montrer
ici.
|