Concevoir de bonnes extensions
Appliquez les bonnes pratiques et évitez les pièges.
Concevoir de bonnes extensions est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.
Concevoir des extensions appréciées
Les méthodes d’extension sont puissantes, mais cette puissance peut entraîner des abus. Les bonnes extensions semblent faire naturellement partie du type, sont faciles à trouver et ne surprennent jamais l’appelant. Cette leçon présente des recommandations pratiques.
Étendre le comportement, pas l’identité
Privilégiez les extensions pour les comportements utilitaires qui s’intègrent naturellement dans une chaîne. Si une méthode appartient véritablement à un type que vous possédez, faites-en plutôt un membre réel.
using System;
public static class TimeExtensions
{
// A pleasant, focused helper
public static bool IsWeekend(this DayOfWeek day)
=> day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;
}
public class Program
{
public static void Main()
{
Console.WriteLine(DayOfWeek.Sunday.IsWeekend());
Console.WriteLine(DayOfWeek.Monday.IsWeekend());
}
}Garder les méthodes pures autant que possible
Les extensions qui renvoient une nouvelle valeur et évitent les effets secondaires sont les plus faciles à comprendre et à enchaîner. Visez une entrée et une valeur en sortie.
using System;
public static class StringExtensions
{
// Pure: depends only on input, returns a new string
public static string Truncate(this string s, int max)
=> s.Length <= max ? s : s.Substring(0, max) + "...";
}
public class Program
{
public static void Main()
{
Console.WriteLine("Extension methods are great".Truncate(10));
}
}Se prémunir contre les entrées nulles
Comme les appelants peuvent invoquer une extension sur un receveur null, décidez délibérément du comportement attendu. Gérez les valeurs nulles avec élégance ou lancez une ArgumentNullException explicite.
using System;
public static class StringExtensions
{
public static string SafeUpper(this string s)
{
if (s is null) throw new ArgumentNullException(nameof(s));
return s.ToUpper();
}
}
public class Program
{
public static void Main()
{
try { ((string)null).SafeUpper(); }
catch (ArgumentNullException ex) { Console.WriteLine("Caught: " + ex.ParamName); }
Console.WriteLine("ok".SafeUpper());
}
}Choisir des noms faciles à trouver
Les développeurs trouvent les extensions en saisissant le point, puis en parcourant IntelliSense. Des noms clairs fondés sur des verbes et décrivant le résultat rendent vos utilitaires faciles à trouver et explicites.
using System;
using System.Collections.Generic;
public static class CollectionExtensions
{
public static bool HasItems<T>(this ICollection<T> c)
=> c != null && c.Count > 0;
}
public class Program
{
public static void Main()
{
var list = new List<int> { 1 };
Console.WriteLine(list.HasItems());
}
}Regrouper les extensions associées de façon cohérente
Placez les extensions liées à un même concept dans une classe statique et un espace de noms bien nommés. Les importations restent ainsi pertinentes et les utilisateurs peuvent importer exactement les utilitaires dont ils ont besoin.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static IEnumerable<T> TakeFirst<T>(this IEnumerable<T> source, int n)
{
int taken = 0;
foreach (var item in source)
{
if (taken++ >= n) yield break;
yield return item;
}
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3, 4 };
Console.WriteLine(string.Join(",", nums.TakeFirst(2)));
}
}Ne masquez pas les comportements surprenants
Une extension qui semble peu coûteuse, mais effectue un travail coûteux ou dépendant d’un état, déçoit les attentes. Rendez le coût évident ; si elle interroge une base de données ou modifie l’état, nommez-la en conséquence.
using System;
public static class MathExtensions
{
// Cheap and obvious: no hidden cost
public static int ClampMin(this int value, int min)
=> value < min ? min : value;
}
public class Program
{
public static void Main()
{
Console.WriteLine((-3).ClampMin(0));
Console.WriteLine(5.ClampMin(0));
}
}Éviter d’étendre object
Étendre object pollue chaque type du programme avec votre méthode et encombre IntelliSense partout. Ciblez plutôt le type ou l’interface la plus spécifique qui soit pertinente.
using System;
public static class IntExtensions
{
// Specific to int, not object - far less noisy
public static string ToOrdinal(this int n)
{
if (n % 10 == 1 && n % 100 != 11) return n + "st";
if (n % 10 == 2 && n % 100 != 12) return n + "nd";
if (n % 10 == 3 && n % 100 != 13) return n + "rd";
return n + "th";
}
}
public class Program
{
public static void Main()
{
Console.WriteLine(1.ToOrdinal());
Console.WriteLine(22.ToOrdinal());
}
}Privilégier le renvoi de IEnumerable pour les séquences
Pour les opérateurs de séquence, renvoyez IEnumerable<T> et utilisez l’exécution différée. Cela se compose bien et évite de forcer les appelants à matérialiser des données dont ils n’auront peut-être pas besoin.
using System;
using System.Collections.Generic;
public static class SeqExtensions
{
public static IEnumerable<int> Doubled(this IEnumerable<int> source)
{
foreach (var n in source) yield return n * 2;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
foreach (var n in nums.Doubled()) Console.WriteLine(n);
}
}Une liste de contrôle pour de bonnes extensions
Avant de publier une extension, demandez-vous : son nom est-il clair ? Est-elle pure ou ses effets secondaires sont-ils évidents ? Le comportement avec les valeurs nulles est-il géré ? Le type cible est-il spécifique ? Les éléments sont-ils regroupés de façon cohérente ? Si vous répondez oui à toutes ces questions, vous avez créé un utilitaire que les autres prendront plaisir à utiliser.
using System;
public static class StringExtensions
{
public static string OrDefault(this string s, string fallback)
=> string.IsNullOrEmpty(s) ? fallback : s;
}
public class Program
{
public static void Main()
{
Console.WriteLine("".OrDefault("N/A"));
Console.WriteLine("value".OrDefault("N/A"));
}
}Essayez par vous-même
Appliquez la liste de contrôle : un type cible spécifique, un nom clair, la gestion des valeurs nulles et un résultat pur. Cette petite extension respecte toutes les recommandations.
using System;
using System.Collections.Generic;
public static class DictionaryExtensions
{
// Clear name, specific type, null-safe, pure
public static TValue GetOrDefault<TKey, TValue>(
this IReadOnlyDictionary<TKey, TValue> dict, TKey key, TValue fallback)
{
if (dict == null) return fallback;
return dict.TryGetValue(key, out var value) ? value : fallback;
}
}
public class Program
{
public static void Main()
{
var ages = new Dictionary<string, int> { ["Ann"] = 30 };
Console.WriteLine(ages.GetOrDefault("Ann", -1));
Console.WriteLine(ages.GetOrDefault("Bob", -1));
}
}Vérification rapide
Appliquez les recommandations de conception.
Récapitulatif
Les extensions bien conçues semblent natives et prévisibles.
- Privilégiez les utilitaires purs qui renvoient une valeur et s’enchaînent facilement.
- Décidez du comportement avec les valeurs nulles et documentez-le.
- Utilisez des noms clairs fondés sur des verbes pour faciliter la découverte.
- Ciblez des types ou des interfaces spécifiques, et non
object. - Regroupez les utilitaires associés et renvoyez
IEnumerable<T>pour les séquences.
Apprends C# avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 93
- Leçons
- 346
Questions Fréquemment Posées
La leçon « Concevoir de bonnes extensions » est-elle gratuite ?
Oui — le texte complet de « Concevoir de bonnes extensions » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Concevoir de bonnes extensions » ?
Appliquez les bonnes pratiques et évitez les pièges. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C# Academy ?
Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Concevoir de bonnes extensions » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?
Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Définir des méthodes d’extension
- Étendre les interfaces et les génériques
- Résolution des méthodes d’extension
- Concevoir de bonnes extensions