Liste détaillée des anti‑patterns les plus fréquents en C#, comment les reconnaître et comment les corriger.
var service = ServiceLocator.Resolve<ICache>();
public void CreateUser(string name, string email) { }
Groupe récurrent de paramètres → dépasser en record ou classe.
async void DoWork() { await ... }
async Task.var data = GetAsync().Result;
await.Pollution du thread pool → utiliser I/O async natif.
Utiliser Invoke partout n’est plus nécessaire, Progress<T> publie automatiquement sur le contexte UI.
lock(this) { }
lock("string") { }
Utiliser un verrou privé :
private readonly object _gate = new();
lock(_gate) { }
try { } catch { }
Préférer les exceptions spécifiques, utiliser when filters.
Préférer TryParse et équivalents.
var conn = new SqlConnection(cs);
using var conn = new SqlConnection(cs);
Utiliser le pattern standard + GC.SuppressFinalize(this).
publisher.Changed += OnChanged;
Correction : Array.Empty<T>() ou new List<T>().
Correction : ArgumentNullException.ThrowIfNull(arg).
Solution : utiliser des record pour gérer automatiquement.
var s = "";
for(...) s += part;
Correction : StringBuilder.
Correction : const, enum, nameof.
Correction : DateTimeOffset.UtcNow.
Utiliser CultureInfo.InvariantCulture ou culture choisie.
Appliquer SRP, découper.
// ❌
async void Process() { await DoAsync(); }
// ✅
async Task ProcessAsync() { await DoAsync(); }
// ❌
var data = GetAsync().Result;
// ✅
var data = await GetAsync();
// ❌
throw new ArgumentNullException("user");
// ✅
throw new ArgumentNullException(nameof(user));