http://javenstudio.org - C++ Java 分布式 搜索引擎 Naven's Research Laboratory - Thinking of Life, Imagination of Future
Lambda表达式是查询体系(query architecture)的一个重要部分,扩展方法(Extension methods)是另一个重要组成部分。扩展方法结合了“duck typing”(一种可替代任何类型的类型)的弹性(flexibility)特点,使得动态语言(dynamic languages,如JavaScript)更加流行(popular),同时又有静态型语言(statically typed languages,如C++和Java)的优秀性能(performance)和编译时验证(compile-time validation)的特点。通过扩展方法,第三方(third parties)可以增加使用了新方法的类型(type with new methods)的公共合同(public contract),使得独立型的开发者(individual type authors)还能提供他们对这些方法的自己专门的实现(specialized implementation)。
扩展方法定义在静态类(static classes)里,就像静态方法(static methods)一样,但是它们在CLR元数据(CLR metadata)里却被标记为[System.Runtime.CompilerServices.Extension]。程序语言都被鼓励(encourage)为扩展方法提供一种直观的语法(direct syntax)。在 C# 语言里,扩展方法是由 this 指针(this modifer)标示(indicate)的,它必须应用于(applied to)扩展方法的第一个参数。下面让我们来看看一段最简单的查询操作符(query operator)的定义代码:
扩展方法的第一个参数的类型标示(indicate)扩展的内容所应用(the extension applies to)的类型。在上面的例子中,扩展方法 Where 扩展自 IEnumerable<T> 类型。因为 Where 是一个静态方法(static method),所以我们可以像其他静态方法一样直接调用它(invoke it directly):
然而,扩展方法的一个独特(unique)的特点是我们还可以使用实例的语法(using instance syntax)来调用它:
扩展方法是基于扩展方法的活动范围内(in scope)在编译时(compile-time)决定的(resolved)。当引入(import)一个命名空间(namespace)时(在 C# 里使用 using 语句,在VB 里使用 Import 语句),所有的扩展方法是由从 namespace 带入活动范围(brought into scope)的静态类(static classes)定义的。
标准查询操作符(standard query operators)在 System.Query.Sequence 类型里定义成扩展方法。当检查标准查询操作符时,你将注意到它们中所有的方法根据(in terms of)接口IEnumerable<T> 来定义的(除了 OfType,将在后面介绍它)。这意味着每一个兼容 IEnumerable<T> 接口的信息源(information source)在 C# 语言里通过简单地添加如下的 using 语句就可以获取标准查询操作符:
用户如果想用一个指定的类型(specific type)来替换标准查询操作符,可以在有一致标识(compatible signatures)的指定的类型上定义他们自己的相同名字的方法(same-named methods),另一种方法是通过扩展指定的类型来(extend the specific type)定义相同名字的方法。用户如果想完全避免(eschew)使用标准查询操作符,可以简单地将 System.Query 置于活动范围之外,并且为 IEnumerable<T> 接口写出他们自己的扩展方法就可以了。
按照分析规则,扩展方法被赋予了最低优先权(lowest priority),它们只是在没有相适配(suitable)的目标类型(target type)和它们的基类型(base types)时才被使用。这个规则允许用户自定的类型(user-defined types)提供他们自己的查询操作符,比标准查询操作符更优先使用(take precedence over)。例如,考虑用户自定义 collection 的实现如下:
通过给出这个类的定义,下面的程序:
将使用 MySequence.Where 的实现,而不是扩展方法,因为类实体方法(instance methods)比扩展方法(extension methods)更优先使用。
前面的提及(mentioned earlier)了属于标准操作符(standard operator)一员但不是扩展自基于IEnumerable<T> 接口(IEnumerable<T>-based)的信息源的 OfType 类型,下面让我们来看看 OfTyoe 查询操作符:
OfType 即接受基于IEnumerable<T> 接口的信息源,也接受那些在 .NET Framework 1.0 中出现的非参数化的 IEnumerable 接口(non-parameterized IEnumerable interface)。OfType 操作符允许用户在标准的 .NET collections 类(classic .NET collections)上应用标准查询操作符,就像下面的程序:
在这个例子中,变量 modern 产生了与变量 classic 一样的顺序的数据列表(same sequence of values),但是不同的是它的类型兼容最新的 IEnumerable<T> 代码(modern IEnumerable<T> code),包括标准查询操作符。
OfType 操作符对新的信息源也是有用的,因为它允许从基于类型的信息源(source based on type)中过滤出数据(filtering values from)。当要制作新的顺序的时候(producing the new sequence),OfType 简单的忽略(omits)原有序列的成员(members of the original sequence)就可以了,这是与类型实参(type argument)不相符的。分析下面的程序,目标是将 string 字符串数据从一个有不同种类数据的数组(heterogeneous array)中分解出来:
当在 foreach 语句中列举(enumerate)变量 justStrings 中的数据时,将得到两个依次为“Hello”和“World”的 string 字符串序列(a sequence of two strings )。
待续, 错误难免,请批评指正,译者Naven 2005-10-22
Powered by: C++博客 Copyright © Javen-Studio