Skip to content

Instantly share code, notes, and snippets.

@bizouarn
Last active July 24, 2025 15:10
Show Gist options
  • Save bizouarn/95353ee493c0debdc227d922155cb18f to your computer and use it in GitHub Desktop.
Save bizouarn/95353ee493c0debdc227d922155cb18f to your computer and use it in GitHub Desktop.
Redéfinir ToString() proprement en .net

Redéfinir ToString() proprement en .net

Introduction

La méthode ToString() est une composante clé de l'écosystème .NET. Elle permet d’obtenir une représentation textuelle d’un objet. Bien que pratique pour l’affichage ou le débogage, sa redéfinition (override) est souvent mal utilisée : elle finit par porter une logique métier déguisée, compromettre la clarté du code et introduire des bugs subtils.

Dans ce document, on revient sur ce qu’est réellement ToString(), quand il est pertinent de la redéfinir et surtout quelles erreurs éviter.

1. ToString() n’est pas un getter métier

Beaucoup de développeurs redéfinissent ToString() pour retourner une donnée métier majeure (comme un identifiant ou une propriété essentielle).

Problème

Tu transformes une méthode d'affichage en source de données, ce qui est une violation du principe de responsabilité unique (SRP).
Cela rend ton code :

  • fragile (si ToString() change, tout casse),
  • ambigu (affichage ou logique métier ?),
  • difficile à maintenir.

Mauvais exemple :

public class User
{
    public string Email { get; set; }

    public override string ToString() => Email;
}

// Utilisation en logique métier (à éviter)
if (user.ToString().EndsWith("@entreprise.com"))
{
    // Mauvaise pratique : logique métier via ToString()
    GrantAccess(user);
}

2. ToString() = pour l’humain, pas la machine

L’objectif de ToString() est de faciliter l’interprétation visuelle de l’objet (log, debug, affichage console). Ce n’est pas un format d’échange ni un outil d’accès aux données.

Bon usage :

public override string ToString()
{
    return $"[User] {Nom} ({Email})";
}

Cela donne un affichage lisible :

[User] Alice Dupont ([email protected])

Mais on ne doit jamais écrire :

if (user.ToString().Contains("@entreprise.com")) { ... }

3. Debugging ≠ métier

Certains surchargent ToString() pour aider au debug. C’est OK tant que cela reste limité à un usage humain.
Mais attention :

  • ne jamais injecter de dépendance,
  • ne jamais lancer d’exception métier,
  • ne jamais conditionner la sortie à un état critique.

4. Que mettre dans un ToString() ?

  • Représentation lisible, concise, utile pour le debug.
  • Jamais de données sensibles (tokens, mdp).
  • Stable (ne dépend pas d’un état externe ou mutable).

Exemple propre :

public class Produit
{
    public string Code { get; set; }
    public decimal Prix { get; set; }

    public override string ToString() => $"{Code} - {Prix:C}";
}

5. Bonnes pratiques

Cas d’usage ToString() ?
Affichage en console ✅ Oui
Logs / debug ✅ Oui
Comparaison métier ❌ Non
Conditions / règles de gestion ❌ Non
Sérialisation (JSON, XML, etc.) ❌ Non
Interface utilisateur (UI binding) ⚠️ À éviter

Recommandations

  • Utilise .ToString() pour afficher, pas pour traiter.
  • Si tu veux exposer une information métier, crée une propriété dédiée.
  • Si tu veux sérialiser : utilise JsonSerializer avec ToJson(), pas ToString().
  • Ne confie jamais de logique métier à une méthode pensée pour l’affichage.

Conclusion

  • ToString() est une méthode d’affichage, pas un getter déguisé.
  • Ne l’utilise pas dans tes règles métier.
  • Sois précis, stable et sans effet de bord dans ton implémentation.

Règle d’or : si le contenu de .ToString() est utilisé ailleurs que pour voir l’objet, t’es probablement en train de mal l’utiliser.

Complément

Cas particulier

  • Des types comme Money, Email, etc. peuvent légitimement retourner la valeur principale.
  • Si la représentation sous forme de chaîne d'une instance est sensible à la culture ou peut être formatée de plusieurs manières, implémentez l'interface IFormattable.
  • Si votre type implémente une méthode Parse ou TryParse, un constructeur ou une autre méthode statique qui instancie une instance du type à partir d'une chaîne, vous devez vous assurer que la chaîne renvoyée par la méthode ToString() peut être convertie en une instance d'objet.
  • Pour le binding d'UI. Préférer des propriétés dédiées ou des convertisseurs. Sauf si le rôle de l'objet est spécifiquement l'affichage dans le binding.

Cas générale

  • ToString() peut être appelé fréquemment (logs, debug). Éviter les opérations coûteuses ou les allocations excessives.
  • Établir une convention pour le format (ex: [Type] propriété1 (propriété2)) aide à la lisibilité des logs.
  • ToString() est ~2x plus lent qu’un accès direct à une propriété (.NET 8), mais son impact est négligeable hors d’un contexte d’appels très intensifs.
Method Job Runtime Mean Error StdDev Allocated
Direct .NET 8.0 .NET 8.0 0.0963 ns 0.0154 ns 0.0144 ns -
ToString .NET 8.0 .NET 8.0 0.2338 ns 0.0095 ns 0.0084 ns -
public class Operateur
{
    public Operateur(string syntaxe)
    {
        Syntaxe = syntaxe;
    }
    public string Syntaxe { get; set; }

    public override string ToString() => Syntaxe;
}
    
private Operateur _operateur = new ("T > 0 && T < 10");

[Benchmark]
public string Direct() => _operateur.Syntaxe;

[Benchmark]
public string ToString() => _operateur.ToString();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment