现在的位置: 首页 > 综合 > 正文

C#3.0规范(五)类型推断

2013年06月16日 ⁄ 综合 ⁄ 共 5948字 ⁄ 字号 评论关闭
 

26.1.1 Type inference 类型推断

When a generic method is called without specifying type arguments, a type inference process attempts to infer type arguments for the call. Lambda expressions passed as arguments to the generic method participate in this type inference process.

当不使用特定类型的参数调用一个泛型函数时,类型推断会尝试为此次调用推断参数类型。Lambda表达式传递参数到泛型函数,且参与这次类型推断的过程。

As described in §20.6.4, type inference first occurs independently for each argument. In this initial phase, nothing is inferred from arguments that are lambda expressions. However, following the initial phase, additional inferences are made from lambda expressions using an iterative process. Specifically, inferences are made as long as one or more arguments exist for which all of the following are true:

§20.6.4所描述的那样,类型推断首先发生在每个独立的参数中。在初始化的阶段,如果参数是lambda表达式,那么什么也不推断。然而,紧跟着初始化阶段,额外的推断将被做出,这是使用一个迭代的过程所完成的。尤其是,只要下列条件为真,那么一或多个参数的推断就会被做出:

 

·         The argument is a lambda expression, in the following called L, from which no inferences have yet been made.

·         参数是一个lambda表达式,下称L,并且还没有被推断过类型。

·         The corresponding parameter’s type, in the following called P, is a delegate type with a return type that involves one or more method type parameters.

·         相应的参数类型,下称P,是一个代理类型并且具有一个返回值,而该返回值关联一或多个函数类型参数。

·         P and L have the same number of parameters, and each parameter in P has the same modifiers as the corresponding parameter in L, or no modifiers if L has an implicitly typed parameter list.

·         P L 具有相同数量的参数,并且每个在P中的参数具有相同的修饰符,就如同相应的L的参数,或者可以没有修饰符,如果L具有一个隐式类型的参数列表。

·         P’s parameter types involve no method type parameters or involve only method type parameters for which a consistent set of inferences have already been made.

·         P的参数类型没有参与函数类型参数或者仅参与的函数类型参数是为了一套一致的,已经被做出的推断。

·         If L has an explicitly typed parameter list, when inferred types are substituted for method type parameters in P, each parameter in P has the same type as the the corresponding parameter in L.

·         如果L具有显式类型参数列表,且当推断的类型作为P的函数类型参数的替代品时,每个P中的参数具有相同的,和相应的L中的参数一样的类型。

·         If L has an implicitly typed parameter list, when inferred types are substituted for method type parameters in P and the resulting parameter types are given to the parameters of L, the body of L is a valid expression or statement block.

·         如果L具有一个隐式的参数列表,且当推断的类型作为P的函数类型参数的替代品并且结果参数类型已经由L的参数所给于时,L的主体是一个确实的表达式或者声明块。

·         A return type can be inferred for L, as described below.

·         能够为L的返回类型进行推断,如上所述。

For each such argument, inferences are made from that argument by relating the return type of P with the inferred return type of L and the new inferences are added to the accumulated set of inferences. This process is repeated until no further inferences can be made.

对于每个这样的参数,推断是从参数做出的,这个过程是通过相关联的P的返回类型以及推断的L的返回类型实现的,并且,新的推断会加入到一套已经积累完毕的推断中。这个过程重复到没有推断可以被做出。

For purposes of type inference and overload resolution, the inferred return type of a lambda expression L is determined as follows:

类型推断和重载决断的目的是为了,某个lambda表达式L的推断类型如下而决定的:

 

·         If the body of L is an expression, the type of that expression is the inferred return type of L.

·         如果L的主体是一个表达式,那么表达式的类型是从L的返回类型所推断的。

·         If the body of L is a statement block, if the set formed by the types of the expressions in the block’s return statements contains exactly one type to which each type in the set is implicitly convertible, and if that type is not the null type, then that type is the inferred return type of L.

·         如果L的主体是一个声明块,且如果这套由表达式类型格式化的在该声明块中的返回声明包含确实的一种类型,并且这套类型中每个类型都是可以被隐式转换的,再且那类型不为null类型,那么类型可以从L的返回类型所推断的。

·         Otherwise, a return type cannot be inferred for L.

·         相反的,则返回类型不能够由L推断做出。

As an example of type inference involving lambda expressions, consider the Select extension method declared in the System.Query.Sequence class:

作为一个包含lambda表达式的类型推断的例子,考虑Select这个扩展函数,它被声明在 System.Query.Sequence类中:

namespace System.Query
{
public static class Sequence
{
    public static IEnumerable<S> Select<T,S>(
         this IEnumerable<T> source,
       Func<T,S> selector)
    {
       foreach (T element in source) yield return selector(element);
    }
}
}

Assuming the System.Query namespace was imported with a using clause, and given a class Customer with a Name property of type string, the Select method can be used to select the names of a list of customers:

假设System.Query名称空间是通过using语句导入的,并且给于了一个名为Customer的类,该类具有一个类型为stringName属性,Select函数可以被使用作为选择一组客户名字中的某个:

List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);

The extension method invocation (§26.2.3) of Select is processed by rewriting the invocation to a static method invocation:

Select的扩展函数调用26.2.3)是通过重写掉用为static函数掉用来处理的:

IEnumerable<string> names = Sequence.Select(customers, c => c.Name);

Since type arguments were not explicitly specified, type inference is used to infer the type arguments. First, the customers argument is related to the source parameter, inferring T to be Customer. Then, using the lambda expression type inference process described above, c is given type Customer, and the expression c.Name is related to the return type of the selector parameter, inferring S to be string. Thus, the invocation is equivalent to

既然类型参数没有被显式指定,那么,只有使用类型推断来推导该类型参数。首先,customers的参数关联到源参数,推断TCustomer。接着,使用lambda表达式类型推断进行处理,如上所述,c 被给于Customer类型,并且表达式c.Name关联于一个select语句的返回类型参数,推断Sstring。那么,该调用相等于

Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)

and the result is of type IEnumerable<string>.

并且结果的类型为IEnumerable<string>.

The following example demonstrates how lambda expression type inference allows type information to “flow” between arguments in a generic method invocation. Given the method

下列例子展示了怎么样使用lambda表达式类型推断以便允许类型信息能够“跟随”在参数中,该情况出现在一个泛型函数的调用中。给于的函数为

static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
return f2(f1(value));
}

type inference for the invocation

为该调用所作的类型推断

double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);

proceeds as follows: First, the argument "1:15:30" is related to the value parameter, inferring X to be string. Then, the parameter of the first lambda expression, s, is given the inferred type string, and the expression TimeSpan.Parse(s) is related to the return type of f1, inferring Y to be System.TimeSpan. Finally, the parameter of the second lambda expression, t, is given the inferred type System.TimeSpan, and the expression t.TotalSeconds is related to the return type of f2, inferring Z to be double. Thus, the result of the invocation is of type double.

过程如下:首先,参数"1:15:30"关联于值参,推断Xstring。那么,第一个lambda表达式的参数s推断类型为string,并且TimeSpan.Parse(s)表达式关联于f1的返回类型,推断YSystem.TimeSpan类型。最后,第二个lambda表达式的参数t,给于得推断类型为System.TimeSpan,并且t.TotalSeconds表达式关联于f2的返回类型,推断Zdouble类型。那么,该调用的结果类型为 double

抱歉!评论已关闭.