Maison  >  Article  >  développement back-end  >  Que signifie le paramètre C# avec cela (méthode d'extension)

Que signifie le paramètre C# avec cela (méthode d'extension)

黄舟
黄舟original
2017-02-18 10:24:444346parcourir


Les méthodes d'extension vous permettent d'"ajouter" des méthodes à un type existant sans avoir à créer un nouveau type dérivé, à recompiler ou à modifier le type d'origine. Une méthode d'extension est un type particulier de méthode statique, mais peut être appelée comme une méthode d'instance sur un type d'extension. Pour le code client écrit en C# et Visual Basic, il n'y a pas de différence significative entre l'appel d'une méthode d'extension et l'appel de la méthode réellement définie dans le type.

La méthode d'extension la plus courante est l'opérateur de requête standard LINQ, qui ajoute une fonctionnalité de requête aux types System.Collections.IEnumerable et System.Collections.Generic.IEnumerable Pour utiliser les opérateurs de requête standards, utilisez d'abord using La directive System.Linq les met dans la portée. Ensuite, tout type qui implémente IEnumerable semble avoir des méthodes d'instance telles que GroupBy, OrderBy, Average, etc. Lorsque vous tapez "point" après une instance de type IEnumerable (comme List ou Array), vous pouvez Ces méthodes supplémentaires sont visibles dans la complétion des instructions IntelliSense.

L'exemple suivant montre comment appeler la méthode OrderBy de l'opérateur de requête standard sur un tableau d'entiers. L'expression entre parenthèses est une expression lambda. De nombreux opérateurs de requête standard prennent les expressions lambda comme paramètres, mais ce n'est pas une exigence pour les méthodes d'extension. Voir Lambda pour plus de détails Expressions (Guide de programmation C#).

C#



class ExtensionMethods2    
{    static void Main()
    {            
        int[] ints = { 10, 45, 15, 39, 21, 26 };        var result = ints.OrderBy(g => g);        foreach (var i in result)
        {
            System.Console.Write(i + " ");
        }           
    }        
}//Output: 10 15 21 26 39 45


Extension Les méthodes sont définies comme des méthodes statiques, mais elles sont appelées via la syntaxe de la méthode d'instance. Leur premier paramètre spécifie sur quel type la méthode opère, et le paramètre est préfixé par le modificateur this. Les méthodes d'extension ne sont concernées que si vous importez explicitement l'espace de noms dans votre code source à l'aide de la directive using.

L'exemple suivant montre une méthode d'extension définie pour la classe System.String. Notez qu'il est défini à l'intérieur d'une classe statique non imbriquée et non générique :

C#


namespace ExtensionMethods
{    public static class MyExtensions
    {        public static int WordCount(this String str)
        {            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}


La méthode d'extension WordCount peut être placée dans la portée à l'aide de cette directive using :

using ExtensionMethods;


而且,可以使用以下语法从应用程序中调用该扩展方法:

string s = "Hello Extension Methods";
int i = s.WordCount();


在代码中,可以使用实例方法语法调用该扩展方法。 但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。

有关详细信息,请参阅如何:实现和调用自定义扩展方法(C# 编程指南)。

通常,你更多时候是调用扩展方法而不是实现你自己的扩展方法。 由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。 若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。 例如,若要使用标准查询运算符,请将此 using 指令添加到代码中:


using System.Linq;


(你可能还必须添加对 System.Core.dll 的引用。)你将注意到,标准查询运算符现在作为可供大多数 IEnumerable 类型使用的附加方法显示在 IntelliSense 中。

Que signifie le paramètre C# avec cela (méthode dextension)Que signifie le paramètre C# avec cela (méthode dextension)

尽管标准查询运算符没有显示在 String 的 IntelliSense 中,但它们仍然可用。


Lier les méthodes d'extension au moment de la compilation

Les méthodes d'extension peuvent être utilisées pour étendre une classe ou une interface , Mais les méthodes d'extension ne peuvent pas être remplacées. Une méthode d'extension avec le même nom et la même signature qu'une méthode d'interface ou de classe ne sera jamais appelée. Une fois compilées, les méthodes d'extension ont toujours une priorité inférieure aux méthodes d'instance définies dans le type lui-même. En d'autres termes, si un type a une méthode appelée Process(int i) et que vous avez une méthode d'extension avec la même signature, le compilateur se lie toujours à cette méthode d'instance. Lorsque le compilateur rencontre un appel de méthode, il recherche d'abord une méthode correspondante parmi les méthodes d'instance de ce type. Si aucune méthode correspondante n'est trouvée, le compilateur recherche toutes les méthodes d'extension définies pour le type et se lie à la première méthode d'extension qu'il trouve. L'exemple suivant montre comment le compilateur détermine à quelle méthode d'extension ou méthode d'instance se lier.

Exemple

L'exemple suivant montre comment le compilateur C# détermine s'il doit appeler un méthode Les règles à suivre lors de la liaison à une méthode d'instance ou à une méthode d'extension sur un type. Classe statique Extensions contient des méthodes d'extension définies pour tout type qui implémente IMyInterface. Les classes A, B et C implémentent toutes cette interface. La méthode d'extension

MethodB n'est jamais appelée car son nom et sa signature correspondent exactement aux méthodes déjà implémentées par ces classes.

Si le compilateur ne trouve pas de méthode d'instance avec une signature correspondante, il se lie à la méthode d'extension correspondante (si une telle méthode existe).

C#


// Define an interface named IMyInterface.namespace DefineIMyInterface
{    using System;    public interface IMyInterface
    {        // Any class that implements IMyInterface must define a method
        // that matches the following signature.
        void MethodB();
    }
}// Define extension methods for IMyInterface.namespace Extensions
{    using System;    using DefineIMyInterface;    // The following extension methods can be accessed by instances of any 
    // class that implements IMyInterface.
    public static class Extension
    {        public static void MethodA(this IMyInterface myInterface, int i)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, int i)");
        }        public static void MethodA(this IMyInterface myInterface, string s)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, string s)");
        }        // This method is never called in ExtensionMethodsDemo1, because each 
        // of the three classes A, B, and C implements a method named MethodB
        // that has a matching signature.
        public static void MethodB(this IMyInterface myInterface)
        {
            Console.WriteLine
                ("Extension.MethodB(this IMyInterface myInterface)");
        }
    }
}// Define three classes that implement IMyInterface, and then use them to test// the extension methods.namespace ExtensionMethodsDemo1
{    using System;    using Extensions;    using DefineIMyInterface;    class A : IMyInterface
    {        public void MethodB() { Console.WriteLine("A.MethodB()"); }
    }    class B : IMyInterface
    {        public void MethodB() { Console.WriteLine("B.MethodB()"); }        
    public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
    }    class C : IMyInterface
    {        public void MethodB() { Console.WriteLine("C.MethodB()"); }        
    public void MethodA(object obj)
        {
            Console.WriteLine("C.MethodA(object obj)");
        }
    }    class ExtMethodDemo
    {        static void Main(string[] args)
        {            // Declare an instance of class A, class B, and class C.
            A a = new A();
            B b = new B();
            C c = new C();            // For a, b, and c, call the following methods:
            //      -- MethodA with an int argument
            //      -- MethodA with a string argument
            //      -- MethodB with no argument.

            // A contains no MethodA, so each call to MethodA resolves to 
            // the extension method that has a matching signature.
            a.MethodA(1);           // Extension.MethodA(object, int)
            a.MethodA("hello");     // Extension.MethodA(object, string)

            // A has a method that matches the signature of the following call
            // to MethodB.
            a.MethodB();            // A.MethodB()

            // B has methods that match the signatures of the following
            // method calls.
            b.MethodA(1);           // B.MethodA(int)
            b.MethodB();            // B.MethodB()

            // B has no matching method for the following call, but 
            // class Extension does.
            b.MethodA("hello");     // Extension.MethodA(object, string)

            // C contains an instance method that matches each of the following
            // method calls.
            c.MethodA(1);           // C.MethodA(object)
            c.MethodA("hello");     // C.MethodA(object)
            c.MethodB();            // C.MethodB()
        }
    }
}/* Output:
    Extension.MethodA(this IMyInterface myInterface, int i)
    Extension.MethodA(this IMyInterface myInterface, string s)
    A.MethodB()
    B.MethodA(int i)
    B.MethodB()
    Extension.MethodA(this IMyInterface myInterface, string s)
    C.MethodA(object obj)
    C.MethodA(object obj)
    C.MethodB()
 */

通用准则

通常,建议你只在不得已的情况下才实现扩展方法,并谨慎地实现。 只要有可能,必须扩展现有类型的客户端代码都应该通过创建从现有类型派生的新类型来达到这一目的。 有关详细信息,请参阅继承(C# 编程指南)。

在使用扩展方法来扩展你无法更改其源代码的类型时,你需要承受该类型实现中的更改会导致扩展方法失效的风险。

如果你确实为给定类型实现了扩展方法,请记住以下几点:

  • 如果扩展方法与该类型中定义的方法具有相同的签名,则扩展方法永远不会被调用。

  • 在命名空间级别将扩展方法置于范围中。 例如,如果你在一个名为 Extensions 的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions; 指令置于范围中。

针对已实现的类库,不应为了避免程序集的版本号递增而使用扩展方法。 如果要向你拥有源代码的库中添加重要功能,应遵循适用于程序集版本控制的标准 .NET Framework 准则。 有关详细信息,请参阅程序集版本控制。

 以上就是C# 参数带this是什么意思(扩展方法)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn