D’une manière générale, si vous observez des langages comme C, C++ et C#, vous constaterez ce point clé :
- Un programme C est un ensemble de fonctions et de types de données
- Un programme C++ est un ensemble de fonctions et de classes
- L’essence même d’un programme C#, quant à elle, est constituée de déclarations de types
Le code source d’un exécutable C# (fichier EXE) ou d’une bibliothèque de liens dynamiques (DLL) est composé d’une ou plusieurs déclarations de types.
Les fichiers DLL n’ont pas de point d’entrée Main ; quant aux exécutables (EXE), ils doivent obligatoirement déclarer au moins une classe contenant une méthode nommée Main, qui sert de point de lancement du programme.
Un logiciel de grande taille peut comporter des milliers de types (classes et autres) dans ses sources. Ces grands projets sont généralement développés par plusieurs programmeurs, chacun en charge de modules distincts, ce qui rend inévitable les conflits de noms de types identiques. Comment résoudre ces conflits de dénomination ? C’est le rôle des « espaces de noms » dont nous avons parlé précédemment.
Un espace de noms (namespace) permet de regrouper logiquement un ensemble de déclarations de types liés et de leur attribuer un identifiant commun. Puisqu’un programme n’est rien d’autre qu’un assemblage de déclarations de types interconnectées, les développeurs créent presque systématiquement des espaces de noms personnalisés pour y placer l’ensemble des types du projet.
Pour faire simple, un espace de noms ajoute un nom de groupe à une série de classes. Tout code extérieur à ce groupe doit préciser ce nom de groupe pour accéder aux classes correspondantes.
Imaginons une classe où deux élèves portent exactement le même nom. Les professeurs et camarades ne peuvent pas les distinguer uniquement par leur prénom ; on ajoute alors une mention de groupe, par exemple Tom du groupe A et Tom du groupe B. Les mentions A et B jouent exactement le rôle des espaces de noms.
L’extrait de code ci-dessous présente un programme avec trois déclarations de types, toutes définies au sein d’un espace de noms nommé MyProgram.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloDemo // Déclarer un espace de noms
{
class A // Déclarer le type A (classe)
{
void Fun1() // Fonction
{
// Logique métier du programme
}
}
class B // Déclarer le type B (classe)
{
void Fun1() // Fonction
{
// Logique métier du programme
}
}
class C // Déclarer le type C (classe)
{
static void Main(string[] args) // Point d’entrée Main du programme
{
double pi = 3.14;
string webSite = "foxdevelop.com";
Console.WriteLine($"The Pi is {pi} and the website is {webSite}.");
}
}
}
Langage du code : PHP (php)
Nous détaillerons le fonctionnement des espaces de noms dans les prochains cours.
Un type est un modèle
Puisqu’un programme C# est fondamentalement un ensemble de déclarations de types, maîtriser C# revient à apprendre à créer et manipuler des types. Il faut d’abord comprendre un concept essentiel :
Qu’est-ce qu’un type (Type)
Vous pouvez voir un type comme un modèle de création de structures de données : il n’est pas une structure de données concrète en soi, mais il définit toutes les caractéristiques que possèdent les objets instanciés à partir de ce modèle.
Un type n’est qu’un « plan de conception » ; il n’occupe aucune mémoire à lui seul. La mémoire n’est allouée et les données ne sont stockées qu’après instanciation.
Le type est un plan grâce auquel on construit des objets concrets. C’est comparable au plan d’une maison : à partir d’un seul plan, on peut bâtir une multitude de logements distincts.
Chaque type est défini par trois éléments :
- Son nom
- La structure de stockage des données de ses membres
- Ses comportements et ses contraintes
En C#, tout est un type, y compris les types primitifs natifs du langage.
Voici deux exemples de types natifs : short et int.
Leur structure est la suivante :
| Type short | Type int |
|---|---|
| Nom : short | Nom : int |
| Structure : occupe 2 octets | Structure : occupe 4 octets |
| Comportement : entier 16 bits | Comportement : entier 32 bits |
- Nom : identifiant unique du type (
int/string/nom de classe personnalisée) - Structure de stockage : définit la taille mémoire occupée et l’agencement des champs (ex:
shortutilise systématiquement 2 octets) - Contraintes de comportement : spécifie les opérations autorisées, la plage de valeurs et les méthodes natives (ex:
intsupporte les opérations arithmétiques, plage de valeurs-2^31 ~ 2^31-1)
Instanciation (Instantiate)
Créer un objet de données utilisable à partir du modèle de type avec le mot-clé new
Objet (object) = Instance (instance)
Prenons les types int et short vus précédemment : on peut générer des instances à partir de ces types. Dans l’exemple ci-dessous, pi, age et nums sont des instances créées respectivement à partir des types double, int et short.
namespace HelloDemo
{
class Program
{
static void Main(string[] args)
{
double pi = 3.14;
int age = 12;
short nums = 23;
}
}
}Langage du code : JavaScript (javascript)
En C#, toutes les variables et toutes les données d’un programme sont sans exception des instances d’un type ; il n’existe pas de données sans type associé.
Reportez-vous à l’exemple de code précédent
La classe C de l’exemple est la classe de point d’entrée et respecte toutes les règles des fichiers exécutables :
- C’est un type personnalisé inclus dans l’espace de noms
MyProgram - Il contient une méthode statique
Mainsans valeur de retour, qui agit comme point de démarrage de l’application
C# ne dispose pas seulement du type class
Tous les types déclarables en C# : Classe (class), Structure (struct), Interface (interface), Énumération (enum), Délégué (delegate), Enregistrement (record)
BCL (Base Class Library) : Bibliothèque de classes standard native de .NET, fournissant des types système prédéfinis tels que int, short, string, List<T>, que les développeurs peuvent instancier directement pour les utiliser.
Déclaration de type