Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Identical simple names and type names

Поиск

In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple-name (§7.6.2) is a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name (§3.8), then both possible meanings of E are permitted. The two possible meanings of E.I are never ambiguous, since I must necessarily be a member of the type E in both cases. In other words, the rule simply permits access to the static members and nested types of E where a compile-time error would otherwise have occurred. For example:

struct Color
{
public static readonly Color White = new Color(...);
public static readonly Color Black = new Color(...);

public Color Complement() {...}
}

class A
{
public Color Color; // Field Color of type Color

void F() {
Color = Color. Black; // References Color.Black static member
Color = Color.Complement(); // Invokes Complement() on Color field
}

static void G() {
Color c = Color. White; // References Color.White static member
}
}

Within the A class, those occurrences of the Color identifier that reference the Color type are underlined, and those that reference the Color field are not underlined.

Grammar ambiguities

The productions for simple-name (§7.6.2) and member-access (§7.6.4) can give rise to ambiguities in the grammar for expressions. For example, the statement:

F(G<A,B>(7));

could be interpreted as a call to F with two arguments, G < A and B > (7). Alternatively, it could be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument.

If a sequence of tokens can be parsed (in context) as a simple-name (§7.6.2), member-access (§7.6.4), or pointer-member-access (§18.5.2) ending with a type-argument-list (§4.4.1), the token immediately following the closing > token is examined. If it is one of

() ] }:;,.? ==!= | ^

then the type-argument-list is retained as part of the simple-name, member-access or pointer-member-access and any other possible parse of the sequence of tokens is discarded. Otherwise, the type-argument-list is not considered to be part of the simple-name, member-access or pointer-member-access, even if there is no other possible parse of the sequence of tokens. Note that these rules are not applied when parsing a type-argument-list in a namespace-or-type-name (§3.8). The statement

F(G<A,B>(7));

will, according to this rule, be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument. The statements

F(G < A, B > 7);
F(G < A, B >> 7);

will each be interpreted as a call to F with two arguments. The statement

x = F < A > +y;

will be interpreted as a less than operator, greater than operator, and unary plus operator, as if the statement had been written x = (F < A) > (+y), instead of as a simple-name with a type-argument-list followed by a binary plus operator. In the statement

x = y is C<T> + z;

the tokens C<T> are interpreted as a namespace-or-type-name with a type-argument-list.

Invocation expressions

An invocation-expression is used to invoke a method.

invocation-expression:
primary-expression (argument-listopt)

An invocation-expression is dynamically bound (§7.2.2) if at least one of the following holds:

  • The primary-expression has compile-time type dynamic.
  • At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.

In this case the compiler classifies the invocation-expression as a value of type dynamic. The rules below to determine the meaning of the invocation-expression are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary-expression and arguments which have the compile-time type dynamic. If the primary-expression does not have compile-time type dynamic, then the method invocation undergoes a limited compile time check as described in §7.5.4.

The primary-expression of an invocation-expression must be a method group or a value of a delegate-type. If the primary-expression is a method group, the invocation-expression is a method invocation (§7.6.5.1). If the primary-expression is a value of a delegate-type, the invocation-expression is a delegate invocation (§7.6.5.3). If the primary-expression is neither a method group nor a value of a delegate-type, a binding-time error occurs.

The optional argument-list (§7.5.1) provides values or variable references for the parameters of the method.

The result of evaluating an invocation-expression is classified as follows:

· If the invocation-expression invokes a method or delegate that returns void, the result is nothing. An expression that is classified as nothing is permitted only in the context of a statement-expression (§8.6) or as the body of a lambda-expression (§7.15). Otherwise a binding-time error occurs.

· Otherwise, the result is a value of the type returned by the method or delegate.

Method invocations

For a method invocation, the primary-expression of the invocation-expression must be a method group. The method group identifies the one method to invoke or the set of overloaded methods from which to choose a specific method to invoke. In the latter case, determination of the specific method to invoke is based on the context provided by the types of the arguments in the argument-list.

The binding-time processing of a method invocation of the form M(A), where M is a method group (possibly including a type-argument-list), and A is an optional argument-list, consists of the following steps:

· The set of candidate methods for the method invocation is constructed. For each method F associated with the method group M:

o If F is non-generic, F is a candidate when:

· M has no type argument list, and

· F is applicable with respect to A (§7.5.3.1).

o If F is generic and M has no type argument list, F is a candidate when:

· Type inference (§7.5.2) succeeds, inferring a list of type arguments for the call, and

· Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (§4.4.4), and the parameter list of F is applicable with respect to A (§7.5.3.1).

o If F is generic and M includes a type argument list, F is a candidate when:

· F has the same number of method type parameters as were supplied in the type argument list, and

· Once the type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (§4.4.4), and the parameter list of F is applicable with respect to A (§7.5.3.1).

· The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set. Furthermore, if C is a class type other than object, all methods declared in an interface type are removed from the set. (This latter rule only has affect when the method group was the result of a member lookup on a type parameter having an effective base class other than object and a non-empty effective interface set.)

· If the resulting set of candidate methods is empty, then further processing along the following steps are abandoned, and instead an attempt is made to process the invocation as an extension method invocation (§7.6.5.2). If this fails, then no applicable methods exist, and a binding-time error occurs.

· The best method of the set of candidate methods is identified using the overload resolution rules of §7.5.3. If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. When performing overload resolution, the parameters of a generic method are considered after substituting the type arguments (supplied or inferred) for the corresponding method type parameters.

· Final validation of the chosen best method is performed:

o The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple-name or a member-access through a type. If the best method is an instance method, the method group must have resulted from a simple-name, a member-access through a variable or value, or a base-access. If neither of these requirements is true, a binding-time error occurs.

o If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (§4.4.4) declared on the generic method. If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.

Once a method has been selected and validated at binding-time by the above steps, the actual run-time invocation is processed according to the rules of function member invocation described in §7.5.4.

The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. Then perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. If no method was found, try instead to process the invocation as an extension method invocation.



Поделиться:


Последнее изменение этой страницы: 2016-08-10; просмотров: 286; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.137.164.229 (0.006 с.)