您的位置:首页 > 编程语言 > C#

C# 3.0新特性之扩展函数

2007-10-30 10:16 225 查看

26.1 Extension methods扩展函数

Extension methods are static methods that can be invoked using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods.

扩展函数是static函数,它能够使用实例函数句法调用。扩展函数有效地使得扩展现有类型以及使用额外函数构造类型变为可能

Note注意

Extension methods are less discoverable and more limited in functionality than instance methods. For those reasons, it is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible.

扩展函数在功能性函数中比在实例函数中更少被使用并且更有局限性。由于这些理由,我们推荐吝啬地使用扩展函数并且仅仅当实例函数行不通或不可能使用的时候才使用它。

Extension members of other kinds, such as properties, events, and operators, are being considered but are currently not supported.

其余类型的扩展成员,例如属性,事件,以及操作符,正在考虑中,但是现在还不被(编译器)支持。

26.1.1 Declaring extension methods声明扩展函数

Extension methods are declared by specifying the keyword this as a modifier on the first parameter of the methods. Extension methods can only be declared in static classes. The following is an example of a static class that declares two extension methods:

扩展函数使用特定的关键字this作为修饰符应用于函数的第一个参数来声明。扩展函数只能声明在static的类中,以下是一个static类,声明两个扩展函数的例子:

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 ArgumentException();
T[] result = new T[count];
Array.Copy(source, index, result, 0, count);
return result;
}
}
}

Extension methods have all the capabilities of regular static methods. In addition, once imported, extension methods can be invoked using instance method syntax.

扩展函数具有常规static函数的一切能力。额外的,一旦导入,扩展函数能够被使用实例函数的句法所调用。

26.1.2 Importing extension methods导入扩展函数

Extension methods are imported through using-namespace-directives (§9.3.2). In addition to importing the types contained in a namespace, a using-namespace-directive imports all extension methods in all static classes in the namespace. In effect, imported extension methods appear as additional methods on the types that are given by their first parameter and have lower precedence than regular instance methods. For example, when the Acme.Utilities namespace from the example above is imported with the using-namespace-directive

扩展函数通过using-namespace-directives (§9.3.2)导入。另外导入的有,该namespace所包含的类型,using-namespace-directive 导入所有的扩展函数在该namespace中的所有static类。被导入的扩展函数有效地作为在某些类型上的额外函数,这是通过它们的第一个关键字以及比常规的实例函数更低的优先级所给与的。例如,当Acme.Utilities namespace在下面这个例子的开头被使用 using-namespace-directive导入后,

using Acme.Utilities;

it becomes possible to invoke the extension methods in the static class Extensions using instance method syntax:

这使得通过实例函数句法调用static类Extensions 的扩展函数成为可能:

string s = "1234";
int i = s.ToInt32(); // Same as Extensions.ToInt32(s)

int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] a = digits.Slice(4, 3); // Same as Extensions.Slice(digits, 4, 3)

26.1.3 Extension method invocations扩展函数的调用

The detailed rules for extension method invocation are described in the following. In a method invocation (§7.5.5.1) of one of the forms

扩展函数调用的详细规则将在下面描述。在函数调用(§7.5.5.1)任一形式中

expr . identifier ( )

expr . identifier ( args )

expr . identifier < typeargs > ( )

expr . identifier < typeargs > ( args )

if the normal processing of the invocation finds no applicable instance methods (specifically, if the set of candidate methods for the invocation is empty), an attempt is made to process the construct as an extension method invocation. The method invocation is first rewritten to one of the following, respectively:

如果正常的调用过程中没有发现适用的实例函数(尤其如果对此调用的候选函数为空的情况下),编译器将做出尝试将构造过程作为扩展函数来调用。函数调用是先各自重写下列中的一个的:

identifier ( expr )

identifier ( expr , args )

identifier < typeargs > ( expr )

identifier < typeargs > ( expr , args )

The rewritten form is then processed as a static method invocation, except for the way in which identifier is resolved: Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to process the rewritten method invocation with a method group consisting of all accessible extension methods with the name given by identifier imported by the namespace declaration’s using-namespace-directives. The first method group that yields a non-empty set of candidate methods is the one chosen for the rewritten method invocation. If all attempts yield empty sets of candidate methods, a compile-time error occurs.

重写的格式是被视作static函数调用处理,除非identifier被解析:开始使用最近的namespace声明,接着使用次近namespace声明,最后包含编译单元,逐次尝试被用来处理重写函数调用,这是通过一个函数群实现的,该函数群由所有准入的扩展函数所组成,它的名称是由identifier给与的,identifier导入是由名称空间声明的using-namespace-directives实现的。第一个函数群产生一套非空的候选函数,其中有一个函数会被选中,来作为重写函数的调用。如果所有的尝试都产生空的候选函数,这将导致一个编译时刻的错误。

The preceeding rules mean that instance methods take precedence over extension methods, and extension methods imported in inner namespace declarations take precedence over extension methods imported in outer namespace declarations. For example:

前述的规则意味着实例函数优先于扩展函数,并且名称空间内的扩展函数优先于通过名称空间导入的扩展函数。例如:

using N1;

namespace N1
{
public static class E
{
public static void F(this object obj, int i) { }

public static void F(this object obj, string s) { }
}
}

class A { }

class B
{
public void F(int i) { }
}

class C
{
public void F(object obj) { }
}

class X
{
static void Test(A a, B b, C c) {
a.F(1); // E.F(object, int)
a.F("hello"); // E.F(object, string)

b.F(1); // B.F(int)
b.F("hello"); // E.F(object, string)

c.F(1); // C.F(object)
c.F("hello"); // C.F(object)
}
}

In the example, B’s method takes precedence over the first extension method, and C’s method takes precedence over both extension methods.

在例子中,B的函数优先于前面的扩展函数,并且C的函数优先于所有的扩展函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐