C# Language Méthodes d'extension - aperçu


Exemple

Les méthodes d'extension ont été introduites dans C # 3.0. Les méthodes d'extension étendent et ajoutent un comportement aux types existants sans créer un nouveau type dérivé, recompiler ou modifier le type d'origine. Ils sont particulièrement utiles lorsque vous ne pouvez pas modifier la source d'un type que vous souhaitez améliorer. Des méthodes d'extension peuvent être créées pour les types de systèmes, les types définis par des tiers et les types que vous avez définis vous-même. La méthode d'extension peut être appelée comme s'il s'agissait d'une méthode membre du type d'origine. Cela permet le chaînage de méthode utilisé pour implémenter une interface Fluent .

Une méthode d'extension est créée en ajoutant une méthode statique à une classe statique distincte du type d'origine étendu. La classe statique contenant la méthode d'extension est souvent créée dans le seul but de conserver les méthodes d'extension.

Les méthodes d'extension prennent un premier paramètre spécial qui désigne le type d'origine étendu. Ce premier paramètre est décoré avec le mot - clé this ( ce qui constitue une utilisation particulière et distincte de this en C # -it doit être comprise comme différent de l'utilisation de this qui permet référence aux membres de l'instance de l' objet).

Dans l'exemple suivant, le type d'origine en cours d'extension est la string classe. String a été étendue par une méthode Shorten() , qui fournit la fonctionnalité supplémentaire de raccourcissement. La classe statique StringExtensions a été créée pour contenir la méthode d'extension. La méthode d'extension Shorten() montre qu'il s'agit d'une extension de string via le premier paramètre spécialement marqué. Pour montrer que la méthode Shorten() étend la string , le premier paramètre est marqué avec this . Par conséquent, la signature complète du premier paramètre est this string text , où string est le type d'origine en cours d'extension et text est le nom du paramètre choisi.

static class StringExtensions
{
    public static string Shorten(this string text, int length) 
    {
        return text.Substring(0, length);
    }
}

class Program
{
    static void Main()
    {
        // This calls method String.ToUpper()
        var myString = "Hello World!".ToUpper();

        // This calls the extension method StringExtensions.Shorten()
        var newString = myString.Shorten(5); 

        // It is worth noting that the above call is purely syntactic sugar
        // and the assignment below is functionally equivalent
        var newString2 = StringExtensions.Shorten(myString, 5);
    }
}

Démo en direct sur .NET Fiddle


L'objet transmis en tant que premier argument d'une méthode d'extension (qui est accompagné du mot this clé this ) est l'instance à laquelle la méthode d'extension est appelée.

Par exemple, lorsque ce code est exécuté:

"some string".Shorten(5);

Les valeurs des arguments sont les suivantes:

text: "some string"
length: 5

Notez que les méthodes d'extension ne sont utilisables que si elles se trouvent dans le même espace de nommage que leur définition, si l'espace de nom est importé explicitement par le code à l'aide de la méthode d'extension ou si la classe d'extension est sans espace de noms. Les directives du framework .NET recommandent de placer les classes d'extension dans leur propre espace de noms. Cependant, cela peut entraîner des problèmes de découverte.

Cela n'entraîne aucun conflit entre les méthodes d'extension et les bibliothèques utilisées, sauf si les espaces de noms susceptibles d'entrer en conflit sont explicitement intégrés. Par exemple, les extensions LINQ :

using System.Linq; // Allows use of extension methods from the System.Linq namespace

class Program
{
    static void Main()
    {
        var ints = new int[] {1, 2, 3, 4};

        // Call Where() extension method from the System.Linq namespace
        var even = ints.Where(x => x % 2 == 0); 
    }
}

Démo en direct sur .NET Fiddle


Depuis C # 6.0, il est également possible de placer une directive using static dans la classe contenant les méthodes d’extension. Par exemple, en using static System.Linq.Enumerable; . Cela rend les méthodes d'extension de cette classe particulière disponibles sans amener d'autres types du même espace de noms dans la portée.


Lorsqu'une méthode de classe avec la même signature est disponible, le compilateur le hiérarchise sur l'appel de la méthode d'extension. Par exemple:

class Test
{
   public void Hello()
   {
       Console.WriteLine("From Test");
   }
}

static class TestExtensions
{
    public static void Hello(this Test test)
    {
        Console.WriteLine("From extension method");
    }
}

class Program
{
    static void Main()
    {
        Test t = new Test();
        t.Hello(); // Prints "From Test"
    }
}

Démo en direct sur .NET Fiddle


Notez que s'il y a deux fonctions d'extension avec la même signature et que l'une d'entre elles se trouve dans le même espace de nommage, alors celle-ci sera prioritaire. D'un autre côté, si les deux sont accessibles en using , alors une erreur de compilation s'ensuivra avec le message:

L'appel est ambigu entre les méthodes ou propriétés suivantes


Notez que la commodité syntaxique d'appeler une méthode d'extension via originalTypeInstance.ExtensionMethod() est une commodité facultative. La méthode peut également être appelée de manière traditionnelle, de sorte que le premier paramètre spécial est utilisé comme paramètre de la méthode.

C'est-à-dire les deux travaux suivants:

//Calling as though method belongs to string--it seamlessly extends string
String s = "Hello World";
s.Shorten(5);  

//Calling as a traditional static method with two parameters
StringExtensions.Shorten(s, 5);