Les méthodes d'extension en C#

31. July 2011 17:07 by Renaud in   //  Tags:   //   Comments (0)
Lors des entretiens d'embauche que j'ai récemment passés, j'ai eu à répondre à pas mal de questions techniques sur le .NET en général. Et à plusieurs reprises, j'me suis retrouvé face à des sujets dont je ne connaissais rien. Soit parce que je n'en avais jamais entendu parler, soit parce que cela ne m'avait pas semblé utile et que je ne m'y étais pas intéressé. Cela n'a rien d'étonnant me direz-vous, mais j'ai pris la peine de noter les différents points après chaque entretien, histoire de me renseigner! Parce qu'après tout, comment pourrais-je penser que ma solution est la plus adaptée si je ne connais pas la moitié du quart des possibilités? Il n'y a certainement pas de solution ultime à un problème donné, mais élargir mes horizons ne pourra que m'aider à réfléchir en connaissance de cause.

 

À quoi servent les méthodes d'extension?

Cette technique permet, comme le nom le suggère, d'étendre les possibilités d'une classe.

Info: Ce type de méthodes a été introduit à partir de C# version 3.

Cela permet d'appeler des méthodes sur un objet exactement de la même manière que si cette méthode était définie dans la classe de l'objet.

Prenons par exemple la classe List! On voit qu'en plus d'une liste de méthodes, cette classe possède une liste de méthodes d'extension. Prenons la méthode ElementAt:

[caption id="attachment_290" align="aligncenter" width="758" caption="Méthode d'extension - List.ElementAt"]Méthode d'extension - List.ElementAt[/caption]

La description indique que cette méthode est définie dans Enumerable, qui est en fait une classe statique fournissant un ensemble de méthodes pour les implémentations de IEnumerable<T>. Mais lorsque vous manipulez une liste, cela ne fait aucune différence pour vous. Vous utilisez ces méthodes comme des méthodes d'instance classique.

Comment créer une méthode d'extension?

Commençons par un exemple abstrait pour vous montrer la syntaxe:

La classe MaClasse possède une méthode.

namespace ConsoleApplication1.Classes
{
    public class MaClasse
    {
        public void MethodeA()
        {
            Console.WriteLine("MethodeA fait un truc cool.");
        }
    }
}

On aimerait y ajouter une seconde méthode en utilisant la technique d'extension. On va donc créer une classe static (puisque'elle ne servira pas à instancier d'objet), et y déclarer une méthode static elle aussi, avec une syntaxe particulière: le mot clé this précède le premier paramètre qui est du type que l'on veut étendre.

using ConsoleApplication1.Classes;

namespace ConsoleApplication1.Extension
{
    public static class MaClasseExtension
    {
        public static void MethodeB(this MaClasse m)
        {
            Console.WriteLine("MethodeB fait un truc super cool!");
        }
    }
}

Et enfin on utilise cette méthode comme n'importe quelle autre:

using ConsoleApplication1.Classes;
using ConsoleApplication1.Extension;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MaClasse maClasse = new MaClasse();
            maClasse.MethodeA();
            maClasse.MethodeB();

            // On attend une entrée.
            Console.ReadKey();
        }
    }
}

Pour que cela fonctionne, il ne faut pas oublier d'importer le namespace contenant les déclarations des méthodes d'extension. Une fois que l'import est fait, l'IntelliSense de VisualStudio vous permet de travailler normalement avec ces méthodes avec une simple indication supplémentaire: (extension)

[caption id="attachment_310" align="aligncenter" width="411" caption="maClasse.MethodeB() - IntelliSense VS2010"]maClasse.MethodeB() - IntelliSense VS2010[/caption]

Il est également possible de créer des méthodes prenant en compte des paramètres:

        public static void MethodeC(this MaClasse m, int i)
        {
            Console.WriteLine("MethodeC affiche l'entier i: {0}", i);
        }

 

            MaClasse maClasse = new MaClasse();
            maClasse.MethodeC(10);

Quand utiliser les méthodes d'extension?

Cette technique n'est évidemment pas à utiliser à tout berzingue!

Imaginons que vous utilisiez dans votre projet une classe X développée par une autre société. Vous y ajoutez une méthode d'extension. Quelques temps plus tard la société améliore la classe X et y ajoute une méthode avec la même signature que la vôtre. Dans ce cas, ce sera toujours la méthode déclarée dans la classe qui prévaudra!

En principe, et c'est ce que conseille Microsoft dans ses guidelines, il est préférable de modifier directement la classe que vous aimeriez étoffer ou de créer une nouvelle classe héritant de celle-ci. Toutefois, il existe des situations dans lesquelles cela n'est pas possible: si vous ne disposez pas du code source de la classe à laquelle vous voulez ajouter une méthode, ou si cette classe est marquée par le modificateur sealed.

Le mot-clé sealed préfixant une classe indique que cette classe ne peut pas être héritée!

La classe String du Framework .NET est un exemple de classe sealed et il est courant de rencontrer des méthodes d'extensions pour cette classe.

[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class String : IComparable,
	ICloneable, IConvertible, IComparable, IEnumerable,
	IEnumerable, IEquatable

 

Pour récapituler,

les méthodes d'extension peuvent être utiles pour simplifier le code dans certains cas. C'est bien de savoir qu'elles existent, mais ne les utilisez que si nécessaire. C'est bien plus clair de retrouver tout le code dans une classe plutôt qu'éparpillé à droite à gauche.

Il ne semble pas y avoir de convention de nommage à ce sujet et Microsoft ne suit d'ailleurs pas cette règle (cf. Enumerable), mais donner un nom significatif aux classes contenant les définitions des méthodes d'extension pourrait rendre les choses plus claires: Exemple: [namespace].[ClassName]Extensions, avec ClassName étant le nom de la classe à étendre. On peut également suffixer les méthodes d'extension de cette manière: [NomDeMethode]Ext. Cela éviterait de voir apparaître une méthode avec la même signature dans le code source de la classe étendue, tout en maintenant une cohérence dans les noms lorsqu'on recherche une méthode avec l’auto-complétion!

Les dernières vacances de ma vie!

15. July 2011 23:07 by Renaud in   //  Tags:   //   Comments (0)

Je profite un peu de ce mois de juillet pour passer du temps avec ma chérie dans le sud de la France. Sérieusement, la piscine avec ce soleil c'est vraiment le top! :)

J'en profite oui, parce que j'ai signé mon premier contrat fin juin chez RealDolmen et que je commence à bosser le 1er août! Du coup j'essaie de ne pas passer trop de temps devant mon laptop, histoire de recharger les batteries pour les mois à venir.

J'ai pas mal réfléchi avant de signer. J'ai pris le temps de faire le tour des possibilités. C'est vrai qu'après avoir fait un stage au MIC, on a de très bonnes références et ça aide à trouver du boulot. Autant dire que le risque de rester à ne rien faire est de zéro. L'avantage c'est que ça m'a donné le choix, en plus d'une expérience incroyable. Maintenant à moi de me démerder pour continuer dans cette voie.

Mais pour le moment, c'est détente, apéro et grillades! Je profite tant que je peux et je me tiens prêt pour la deuxième moitié de l'été.

TextBox

About the author

I'm a developer, blog writer, and author, mainly focused on Microsoft technologies (but not only Smile). I'm Microsoft MVP Client Development since July 2013.

Microsoft Certified Professional

I'm currently working as an IT Evangelist with an awesome team at the Microsoft Innovation Center Belgique, where I spend time and energy helping people to develop their projects. I also give training to enthusiastic developers and organize afterworks with the help of the Belgian community.

MIC Belgique

Take a look at my first book (french only): Développez en HTML 5 pour Windows 8

Développez en HTML5 pour Windows 8

Membre de l'association Fier d'être développeur

TextBox

Month List