代码改变世界

扩展方法

2014-03-05 08:55  观海看云  阅读(156)  评论(0编辑  收藏  举报

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。

最常见的扩展方法是 LINQ 标准查询运算符,它将查询功能添加至现有的 System.CollectionsIEnumerable  System.Collections.GenericIEnumerableT 类型。 若要使用标准查询运算符,请首先使用using System.Linq指令将它们置于范围中。 然后,任何实现了 IEnumerableT 的类型看起来都具有 GroupBy OrderBy Average 等实例方法。  IEnumerableT 类型的实例(如 ListT  Array)后键入“dot”时,可以在 IntelliSense 语句完成中看到这些附加方法。

下面的示例演示如何对一个整数数组调用标准查询运算符 OrderBy 方法。 括号里面的表达式是一个 lambda 表达式。 很多标准查询运算符采用 lambda 表达式作为参数,但这不是扩展方法的必要条件。 有关详细信息,请参阅 Lambda 表达式(C# 编程指南)

class ExtensionMethods2     

 
    static void Main() 
    {             
        int[] ints = { 104515392126 }; 
        var result = ints.OrderBy(g => g); 
        foreach (var i in result) 
        { 
            System.Console.Write(i + " "); 
        }            
    }         

//Output: 10 15 21 26 39 45 
 

扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 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) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。

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

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

using System.Linq;

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

说明说明

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