Types de données & Variables
C# est un langage fortement typé.
Valeurs vs références
Il existe deux principales catégories de types en C# :
Valeurs
Stockage : la donnée est stockée directement à l’emplacement mémoire de la variable.
Types concernés : int, byte, bool, char
Allocation mémoire :
- Sur la pile (stack) : si déclarés dans une méthode.
- Sur le tas (heap) : s’ils sont membres d’une classe.
Références
Stockage : la variable contient un pointeur (référence) vers une donnée stockée ailleurs en mémoire.
Types concernés : string, arrays, classes
Allocation mémoire : toujours alloués sur le tas (heap)
Détail des types
| Type | Description | Taille octet | Eq .NET |
|---|---|---|---|
bool | Valeurs booléennes (true ou false) | 1 | System.Boolean |
int | Nombres entiers | 4 | System.Int32 |
long | Nombre entier (étendu) | 8 | System.Int64 |
float | Nombres flottants | 4 | System.Single |
double | Nombres flottants (plus précis) | 8 | System.Double |
decimal | Valeurs monétaires | 16 | System.Decimal |
char | Caractère unique | 2 | System.Char |
string | Séquence de caractères | 2 / char | System.String |
DateTime | Date | 8 | System.DateTime |
Entiers et flottants
Entiers (integers)
Un entier est un nombre entier (ex. -2, 0, 42 etc.).
S’il est négatif, il va alors être qualifié de signé (car présence du signe - qui utilise 1 bit)
Par défaut, pour les nombres positifs, on peut parler de non signés (unsigned).
int sInt = -20;
uint uInt = 20;
byte sByte = 256;| Type | Taille | Signe | Plage approximative |
|---|---|---|---|
sbyte | 8 bits | Signé | -128 à 127 |
byte | 8 bits | Non signé | 0 à 255 |
short | 16 bits | Signé | -32 768 à 32 767 |
ushort | 16 bits | Non signé | 0 à 65 535 |
int | 32 bits | Signé | -2,1 Mrd à 2,1 Mrd |
uint | 32 bits | Non signé | 0 à 4,2 Mrd |
long | 64 bits | Signé | Très grand |
ulong | 64 bits | Non signé | Très grand (positif seulement) |
Flottants (floats)
Un flottant est un nombre à virgule (ex. 3.14, -0.5).
Tous les flottants sont signés et varient par précision et taille mémoire :
float piFloat = 3.14159265359F;
double piDouble = 3.14159265359D;| Type | Taille | Précision | Suffixe obligatoire |
|---|---|---|---|
float | 4 octets | ~ 6/9 chiffres | F (ex. 3.14F) |
double | 8 octets | ~ 15/16 chiffres | D (ex. 3.14D) |
decimal | 16 octets | ~ 28/29 chiffres (très précis) | Pas obligatoire |
Booléens et caractères
Booléens (booleans)
Un booléen est une valeur true ou false.
bool myBool = true;Caractères
Un caractère représente un caractère unique (lettre, chiffre, symbole etc.) Il utilise des apostrophes simples pour être définis et occupe 2 octets (16 bits). Compatible avec les standards ASCII et Unicode.
char lettre = 'A';
char chiffre = '7';
char symbole = '$';Arrays et tuples (collections)
Arrays
Un array est un tableau qui contient plusieurs valeurs du même type. Il possède une taille fixe définie à l’initialisation.
// Initialiser un array avec des valeurs
int[] intArray = { 1, 2, 3, 4 };
// Créer un array vide avec une taille fixe
int[] intArray = new int[5];Les éléments sont accessibles par leur index (array[0], array[1], etc.).
Les arrays sont indexés à partir de 0 (zero-based).
int[] intArray = { 1, 2, 3, 4 };
// Pour appeler le 3ème élément
Console.WriteLine(intArray[2]);Identifier la longueur d’un array
int[] intArray = { 1, 2, 3, 4 };
// arrayLength will be 4
int arrayLength = intArray.Length;Trier un array
La méthode Array.Sort() permet de trier un array de façon logique :
int[] plantHeights = { 3, 6, 4, 1 };
// plantHeights will be { 1, 3, 4, 6 }
Array.Sort(plantHeights);Récupérer l’index d’une valeur
La méthode Array.IndexOf() permet de récupérer l’index d’une valeur d’un array :
int[] plantHeights = { 3, 6, 4, 1, 6, 8 };
// Returns 1
Array.IndexOf(plantHeights, 6);Retourner un array inversé
La méthode Array.Reverse() permet de retourner le contenu d’un array avec les éléments inversés :
int[] plantHeights = { 3, 6, 4, 1, 6, 8 };
// plantHeights will be { 8, 6, 1, 4, 6, 3 }
Array.Reverse(plantHeights);Tuples
Un tuple peut contenir plusieurs valeurs de types différents. Il possède également une taille fixe définie à l’initialisation. Il utilise les parenthèses pour l’identification des types et l’attribution des valeurs.
(string, string, int) myTuple = ("Charles", "Alice", 15);Les éléments sont accessibles via des propriétés nommées (Item1, Item2, etc.).
(string, string, int) myTuple = ("Charles", "Alice", 15);
// Pour appeler le 2ème élément
Console.WriteLine(myTuple.Item2);Enfin, on peut utiliser le concept de déconstruction pour assigner des variables à des éléments d’un tuple.
(string, string, int) myTuple = ("Charles", "Alice", 15);
(string brother, string sister, int age) = myTuple; // Définition de variables
Console.WriteLine(sister); // Affiche "Alice"
Chaînes de caractères (strings)
Une chaîne se déclare avec des guillemets doubles (" ").
string message = "Hello world";Concaténer des chaînes de caractères
string firstName = "Chuck";
string lastName = "NORRIS";
// Concaténer ave un "+"
string fullName = firstName + " " + lastName;
// Concaténation avec une interpolation
string fullName = $"{firstName} {lastName}";
// Concaténation avec la méthode .Concat()
string fullName = string.Concat(firstName, " ", lastName);Méthodes à retenir
Split()Join()Equals()IsNullOrEmpty()IsNullOrWhiteSpace()
.ToUpper() : Permet de convertir chaque caractères en majuscule.
string str2 = "Chuck";
string upperstr2 = str2.ToUpper();
//upperstr2 contient "CHUCK"
.ToLower() : Permet de convertir chaque caractères en minuscule.
string str2 = "CHUCK";
string upperstr2 = str2.ToLower();
//upperstr2 contient "chuck"
.IndexOf() : Permet de retrouver la position en index d’un caractère dans une string. Cette méthode retourne -1 si le caractère n’est pas trouvé.
string str = "Chuck";
int index1 = str.IndexOf('s')
Console.WriteLine("The Index Value of character 's' is " + index1);
//The Index Value of character 's' is 5
A l’inverse, si on veut retrouver un caractère à partir d’un index, on va utiliser les crochets :
string value = "Dot Net Perls";
char first = value[0]; // Contient "D"
char second = value[1]; // Contient "o"
char last = value[value.Length - 1]; // Contient la dernière lettre "s"
.Substring() : Permet de récupérer une partie d’une chaîne de caractères en gardant la valeur originale intacte.
Types génériques
Un type générique permet d’écrire du code réutilisable et flexible en utilisant un paramètre de type comme T au lieu d’un type concret (string, int etc.). L’avantage est d’éviter de dupliquer du code pour chaque type.
List<T> // Liste de n’importe quel type
List<Person> // Liste de Person
On peut également utiliser des types génériques dans les méthodes. Dans l’exemple suivant il est alors possible de serialiser/déserialiser n’importe quelle classe.
public static byte[] Serialize<T>(T obj) where T : class
{
return JsonSerializer.SerializeToUtf8Bytes(obj);
}
public static T? Deserialize<T>(byte[] data) where T : class
{
return JsonSerializer.Deserialize<T>(data);
}Avec ce code il est également possible d’ajouter une contrainte de type avec where.
Variables
Une variable est un emplacement en mémoire utilisé pour stocker et manipuler de la donnée.
Déclaration explicite vs implicite
Déclaration explicite
On précise explicitement le type de la variable :
int age = 25;
string nom = "Sophie";Déclaration implicite
Le mot clé var active l’interprétation de type, ce qui permet au compilateur de déterminer automatiquement le type de donnée stocké dans la variable en fonction de la valeur qui y est assignée.
var name = "Shadow"; // Interprété comme une string
var age = 5; // Interprété comme un int
var weight = 65.22; // Interprété comme un double
var isActive = true; // Interprété comme un bool
Variable immuable
Par défaut en C#, toute variable est mutable (modifiable).
Pour créer une variable constante, il faut utiliser le mot clé const :
const double pi = 3.14159D;Il est impossible de modifier sa valeur après sa déclaration.
Conventions de nommage
Voici les principales conventions de nommage en fonction des utilisations :
| Objet | Convention de nommage |
|---|---|
| Classes | PascalCase |
| Membres publics | PascalCase |
| Membres privés | _camelCase |
| Méthodes | PascalCase |
| Variables | camelCase |
| Enums | PascalCase |
Conversion de type (casting)
Dans certaines circonstances, on a besoin de changer le type de valeur qu’une variable stocke. Il existe deux types de conversion :
- Conversion implicite : une conversion automatique sans perte de données.
- Conversion explicite : un conversion forcée avec possible perte de précision (ex. passer d’un
doubleà unint)
double positiveDouble = 3.75
double negativeDouble = -3.75;
// Conversion explicite car perte de données (arrondis)
int positiveInt = (int)positiveDouble; // 3
int negativeInt = (int)negativeDouble; // -3
// Conversion implicite
int a = 10;
double b = a;C’est également possible grâce à certaines méthodes Convert.ToXXX() : Documentation Microsoft
// Conversion d'une string en int avec Convert.ToInt32()
Console.Write("Enter your favorite number!: ");
int faveNumber = Convert.ToInt32(Console.ReadLine());Valeurs par défaut
Lorsqu’une variable est initialisée sans valeur, le typage va permettre de définir une valeur par défaut :
| Type | Valeur par défaut |
|---|---|
string | null |
Int | 0 |
Float, double | 0 |
Modifier la valeur d’une variable
Il est possible de modifier la valeur d’une variable en utilisant des opérateurs.
// Ajouter 100€ à mon budget
monBudget = monBudget + 100;
// Soustraire 100€ à mon budget
monBudget = monBudget - 100;
// Mettre à jour le budget
monBudget = monBudget + (30 - 10) * 7;Attention au typage en sortie suite à une opération mathématique : le résultat sera toujours le plus précis. Ainsi si on fait un calcul entre un int et un double, le typage en sortie sera double.
Console.WriteLine(5 / 3.0); // Prints 1.66667
Scopes
Une portée (scope) est une zone dans laquelle une variable existe et est accessible.
Chaque paire d’accolades { } crée une nouvelle portée :
- Méthodes
- Boucles (
for,while,foreach) - Conditions (
if,switch, etc.)
Les portées peuvent être imbriquées, on parle alors de hiérarchie de scopes.
Lecture interactive et comparaison de chaînes
Lire une entrée utilisateur
string input = Console.ReadLine();Cela peut être utilisé dans une boucle d’interaction avec le mot-clé exit par exemple :
while (true)
{
Console.Write("Commande > ");
string input = Console.ReadLine();
if (input.Equals("exit"))
break;
Console.WriteLine($"Vous avez tapé : {input}");
}Attention, par défaut, la méthode Equals() est sensible à la casse :