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;
}
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
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.
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é.
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.
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.