Extension methods enable you to "add" methods to an existing type without having to create a new derived type, recompile, or otherwise modify the original type. An extension method is a special kind of static method, but can be called like an instance method on an extension type. For client code written in C# and Visual Basic, there is no significant difference between calling an extension method and calling the method actually defined in the type.
The most common extension methods are the LINQ standard query operators, which add query functionality to existing System.Collections.IEnumerable and System.Collections.Generic.IEnumerable
The following example demonstrates how to call the standard query operator OrderBy method on an array of integers. The expression inside the brackets is a lambda expression. Many standard query operators take lambda expressions as parameters, but this is not a requirement for extension methods. For more information, see Lambda Expressions (C# Programming Guide).
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 methods are Defined as static methods, but they are called through instance method syntax. Their first parameter specifies which type the method acts on, and the parameter is prefixed with the this modifier. Extension methods are in scope only if you explicitly import the namespace into your source code using the using directive.
The following example demonstrates an extension method defined for the System.String class. Note that it is defined inside a non-nested, non-generic static class:
C
namespace ExtensionMethods { public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }
You can use this using directive to place the WordCount extension method in scope:
using ExtensionMethods;
而且,可以使用以下语法从应用程序中调用该扩展方法:
string s = "Hello Extension Methods"; int i = s.WordCount();
在代码中,可以使用实例方法语法调用该扩展方法。 但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。
有关详细信息,请参阅如何:实现和调用自定义扩展方法(C# 编程指南)。
通常,你更多时候是调用扩展方法而不是实现你自己的扩展方法。 由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。 若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。 例如,若要使用标准查询运算符,请将此 using 指令添加到代码中:
using System.Linq;
(你可能还必须添加对 System.Core.dll 的引用。)你将注意到,标准查询运算符现在作为可供大多数 IEnumerable
What does C# parameter with this mean (extension method) |
---|
尽管标准查询运算符没有显示在 String 的 IntelliSense 中,但它们仍然可用。 |
Bind extension methods at compile time
You can use extension methods to extend a class or interface, But extension methods cannot be overridden. An extension method with the same name and signature as an interface or class method will never be called. When compiling, extension methods always have lower priority than instance methods defined in the type itself. In other words, if a type has a method named Process(int i) method, and you have an extension method with the same signature, the compiler always binds to that instance method. When the compiler encounters a method call, it first looks for a matching method among the instance methods of the type. If no matching method is found, the compiler searches for any extension methods defined for the type, and binds to the first extension method it finds. The following example demonstrates how the compiler determines which extension method or instance method to bind to.
Example
The following example demonstrates how the C# compiler determines whether to call a method The rules to follow when binding to an instance method or an extension method on a type. Static class Extensions Contains extension methods defined for any type that implements IMyInterface. Classes A, B and C all implement this interface.
MethodB The extension method is never called because its name and signature exactly match the methods already implemented by these classes.
If the compiler cannot find an instance method with a matching signature, it binds to a matching extension method if such a method exists.
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)!