Aller au contenu principal

Le mot-clé this

Notions théoriques

this — référence à l'objet courant

this désigne l'instance courante de la classe dans laquelle on se trouve. Il est utilisé pour lever l'ambiguïté entre un champ et un paramètre de même nom, ou pour passer l'objet courant à une méthode.

class Cercle
{
private double _rayon;

// Ici, le paramètre s'appelle aussi "rayon"
public Cercle(double rayon)
{
this._rayon = rayon; // this._rayon = champ | rayon = paramètre
}

public double Surface() => Math.PI * this._rayon * this._rayon;
}
Quand this est-il obligatoire ?

this est obligatoire quand un paramètre ou une variable locale a le même nom qu'un champ. Dans les autres cas, C# résout le nom automatiquement — this est optionnel. Par convention, on préfère le préfixe _ sur les champs pour éviter l'ambiguïté et minimiser l'usage de this.

this avec la convention _underscore

La convention _ élimine le besoin de this dans la plupart des cas :

class Produit
{
private string _nom; // convention _
private decimal _prix;

// Avec _ : pas d'ambiguïté, this inutile
public Produit(string nom, decimal prix)
{
_nom = nom; // pas de this nécessaire
_prix = prix;
}

// Sans _ : this obligatoire pour lever l'ambiguïté
// public Produit(string nom, decimal prix)
// {
// this.nom = nom; // champ nom = paramètre nom
// this.prix = prix;
// }
}

: this(...) — délégation entre constructeurs

Déjà vu dans la séance précédente, : this(...) appelle un autre constructeur de la même classe avant d'exécuter le corps du constructeur actuel :

class Vehicule
{
public string Marque { get; }
public int Annee { get; }
public string Couleur { get; }

public Vehicule(string marque, int annee, string couleur)
{
Marque = marque;
Annee = annee;
Couleur = couleur;
}

// Constructeur simplifié : couleur "Blanc" par défaut
public Vehicule(string marque, int annee) : this(marque, annee, "Blanc") { }

// Constructeur minimal : année courante et couleur blanche
public Vehicule(string marque) : this(marque, DateTime.Now.Year) { }
}

Méthodes fluentes avec return this

return this permet aux méthodes de retourner l'objet courant pour enchaîner les appels (pattern fluent ou builder) :

class QueryBuilder
{
private string _table = "";
private string _where = "";
private int _limite = 100;

public QueryBuilder From(string table)
{
_table = table;
return this; // retourne l'objet courant → permet l'enchaînement
}

public QueryBuilder Where(string condition)
{
_where = condition;
return this;
}

public QueryBuilder Limit(int n)
{
_limite = n;
return this;
}

public string Build()
{
string sql = $"SELECT * FROM {_table}";
if (_where != "") sql += $" WHERE {_where}";
sql += $" LIMIT {_limite}";
return sql;
}
}

// Appels enchaînés — lisible et expressif
string requete = new QueryBuilder()
.From("etudiants")
.Where("note >= 10")
.Limit(20)
.Build();

Console.WriteLine(requete);
// SELECT * FROM etudiants WHERE note >= 10 LIMIT 20

Passer this comme argument

this peut aussi être passé à une méthode externe pour que celle-ci travaille sur l'objet courant :

class Etudiant
{
public string Nom { get; }
public double Note { get; }

public Etudiant(string nom, double note) { Nom = nom; Note = note; }

public void InscrireEn(Classe classe)
{
classe.AjouterEtudiant(this); // passe l'objet courant
}
}

Exemple pratique

class Configuration
{
private string _serveur = "localhost";
private int _port = 3306;
private string _base = "mabase";
private string? _password = null;
private int _timeout = 30;

// Méthodes fluentes
public Configuration Serveur(string serveur) { _serveur = serveur; return this; }
public Configuration Port(int port) { _port = port; return this; }
public Configuration Base(string nomBase) { _base = nomBase; return this; }
public Configuration Password(string mdp) { _password = mdp; return this; }
public Configuration Timeout(int secondes) { _timeout = secondes; return this; }

public string BuildConnectionString()
{
string auth = _password != null ? $"Uid=root;Pwd={_password}" : "Uid=root";
return $"Server={_serveur};Port={_port};Database={_base};{auth};Connect Timeout={_timeout};";
}

public override string ToString()
=> $"[Config] {_serveur}:{_port}/{_base} (timeout={_timeout}s)";
}

// Utilisation fluente
var config = new Configuration()
.Serveur("db.exemple.fr")
.Port(3307)
.Base("production_db")
.Password(Environment.GetEnvironmentVariable("DB_PASSWORD") ?? "changeme")
.Timeout(60);

Console.WriteLine(config);
Console.WriteLine(config.BuildConnectionString());

Test de mémorisation/compréhension


Que désigne `this` dans une méthode d'instance ?


Quand `this` est-il obligatoire ?


Que fait `return this` dans une méthode ?


Quelle est la principale raison d'utiliser la convention `_` pour les champs privés ?


À quoi sert `: this(...)` dans un constructeur ?


TP pour réfléchir et résoudre des problèmes

Vous allez créer un BulletinBuilder pour construire des bulletins scolaires de façon fluente.

Étape 1 — Créer la classe avec méthodes fluentes

Définissez les méthodes qui retournent this pour l'enchaînement.


Bonne pratique - Valider même dans les méthodes fluentes

Même si les méthodes fluentes visent à être concises, n'omettez pas la validation. Il vaut mieux lever une ArgumentOutOfRangeException dans AddNote qu'accepter silencieusement une note de 150 et obtenir des statistiques incorrectes.

Étape 2 — Méthode Build() pour produire le bulletin

Créez la méthode terminale qui construit et retourne le bulletin formaté.


Bonne pratique - Build() comme méthode terminale

Dans un pattern builder, Build() est la méthode finale qui produit le résultat. Elle est la seule à ne pas retourner this. Ce pattern sépare clairement la configuration (méthodes fluentes) de la production du résultat (Build), rendant le code expressif et facile à lire.

Étape 3 — Utiliser le BulletinBuilder de façon fluente

Enchaînez les appels pour créer plusieurs bulletins.


Bonne pratique - Réutiliser le builder pour plusieurs objets

Un BulletinBuilder peut construire plusieurs bulletins différents. Chaque appel à new BulletinBuilder() crée une nouvelle instance indépendante. Le pattern builder est particulièrement utile quand l'objet final est complexe ou quand la configuration varie beaucoup d'un cas à l'autre.

📌 Une solution