日期:2011-04-27  浏览次数:20419 次

原文:《C# Version 3.0 Specification》,Microsoft
翻译:lover_P
扩展方法(Extension Methods)是一种静态方法,可以通过实例方法的语法进行调用。从最终效果上看,扩展方法使得扩展一个现有类型和构造一个具有附加方法的类型变成了现实。

注意

扩展方法很难发觉,并且比起实例方法在功能性上有很大限制。出于这些原因,我们建议保守地使用扩展方法,仅在实例方法不大可行或根本不可行的时候才使用。

扩展成员的其他类型,如属性、事件和运算符都在考虑之中,但目前并未支持。

2.1 声明扩展方法

扩展方法通过在方法的第一个参数上指定关键字this作为一个修饰符来声明。扩展方法只能声明在静态类中。下面的示例是一个声明了两个扩展方法的静态类:

namespace Acme.Utilities

{

    public static class Extensions

    {

        public static int ToInt32(this string s) {

            return Int32.Parse(s);

        }

 

        public static T[] Slice<T>(this T[] source, int index, int count) {

            if(index < 0 || count < 0 || source.Length - index < count)

                throw new ArugmentException();

            T[] result = new T[count];

            Array.Copy(source, index, result, 0, count);

            return result;

        }

    }

}

扩展方法和正常的静态方法具有完全相同的功能。另外,一旦导入了扩展方法,就可以用调用实例方法的语法来调用扩展方法。

2.2 导入扩展方法

扩展方法使用using-namespace-directives导入。除了导入一个命名空间中的类型以外,一个using-namespace-directive还可以导入一个命名空间中所有的静态类中所有的扩展方法。最后,导入的扩展方法表现为其第一个参数的类型的附加方法,并且其优先级比一般的实例方法低。例如,当使用using-namespace-directive导入了上面例子中的Acme.Utilities命名空间时:

using Acme.Utilities;

就可以使用调用实例方法的语法来调用静态类Extensions中的扩展方法了:

string s = "1234";

int i = s.ToInt32();             // 和Extensions.ToInt32(s)一样

int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

int[] a = digits.Slice(4, 3);  // 和Extensions.Slice(digits, 4, 3)一样

2.3 扩展方法的调用

下面描述了扩展方法调用的详细规则。在下面这些形式的方法调用中:

expr  .  identifier  (  )

expr  .  identifier  (  args  )

expr  .  identifier  <  typeargs  >  (  )

expr  .  identifier  <  typeargs  >  (  args  )

如果按照正常的过程没有发现可用的实例方法(确切地说,当待调用的候选方法集合为空时),就会尝试构造一个扩展方法调用。这些方法调用首先被重写为下面相应的形式:

identifier  (  expr  )

identifier  (  expr  ,  args  )

identifier  <  typeargs  >  (  expr  )

identifier  <  typeargs&nb