C#扩展方法入门

扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。 仅当你使用 using 指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。
下面的示例演示为 SystemString 类定义的一个扩展方法。 请注意,它是在非嵌套的、非泛型静态类内部定义的:
namespace ExtensionMethods 
{ 
    public static class MyExtensions 
    { 
        public static int WordCount(this String str) 
        { 
            return str.Split(new char[] { ' ', '.', '?' },  
                             StringSplitOptions.RemoveEmptyEntries).Length; 
        } 
    }    
} 
 
可使用此 using 指令将
WordCount
扩展方法置于范围中:
using ExtensionMethods;
而且,可以使用以下语法从应用程序中调用该扩展方法:
string s = "Hello Extension Methods";
int i = s.WordCount();
在代码中,可以使用实例方法语法调用该扩展方法。 但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。
通常,你更多时候是调用扩展方法而不是实现你自己的扩展方法。 由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。 若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。 例如,若要使用标准查询运算符,请将此 using 指令添加到代码中:

可以使用扩展方法来扩展类或接口,但不能重写扩展方法。 与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。 编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。 换句话说,如果某个类型具有一个名为Process(int i)的方法,而你有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。 当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。 如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法。 下面的示例演示编译器如何确定要绑定到哪个扩展方法或实例方法。

  

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() 
 */ 

  

原文地址:https://www.cnblogs.com/alphafly/p/3872248.html