Language Specification Version 0 Notice



Download 3.2 Mb.
Page26/85
Date29.01.2017
Size3.2 Mb.
#10878
1   ...   22   23   24   25   26   27   28   29   ...   85

6.6Method group conversions


An implicit conversion (§6.1) exists from a method group (§7.1) to a compatible delegate type. Given a delegate type D and an expression E that is classified as a method group, an implicit conversion exists from E to D if E contains at least one method that is applicable in its normal form (§7.4.3.1) to an argument list constructed by use of the parameter types and modifiers of D, as described in the following.

The compile-time application of a conversion from a method group E to a delegate type D is described in the following. Note that the existence of an implicit conversion from E to D does not guarantee that the compile-time application of the conversion will succeed without error.



  • A single method M is selected corresponding to a method invocation (§7.5.5.1) of the form E(A), with the following modifications:

  • The argument list A is a list of expressions, each classified as a variable and with the type and modifier (ref or out) of the corresponding parameter in the formal-parameter-list of D.

  • The candidate methods considered are only those methods that are applicable in their normal form (§7.4.3.1), not those applicable only in their expanded form.

  • If the algorithm of §7.5.5.1 produces an error, then a compile-time error occurs. Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.

  • The selected method M must be compatible (§15.2) with the delegate type D, or otherwise, a compile-time error occurs.

  • If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.

  • If the selected method M is an extension method which is denoted by means of a member access on an instance expression, that instance expression determines the target object of the delegate.

  • The result of the conversion is a value of type D, namely a newly created delegate that refers to the selected method and target object.

    Note that this process can lead to the creation of a delegate to an extension method, if the algorithm of §7.5.5.1 fails to find an instance method but succeeds in processing the invocation of E(A) as an extension method invocation (§7.5.5.2). A delegate thus created captures the extension method as well as its first argument.



The following example demonstrates method group conversions:

delegate string D1(object o);

delegate object D2(string s);

delegate object D3();

delegate string D4(object o, params object[] a);

delegate string D5(int i);

class Test
{
static string F(object o) {...}

static void G() {


D1 d1 = F; // Ok
D2 d2 = F; // Ok
D3 d3 = F; // Error – not applicable
D4 d4 = F; // Error – not applicable in normal form
D5 d5 = F; // Error – applicable but not compatible

}
}


The assignment to d1 implicitly converts the method group F to a value of type D1.

The assignment to d2 shows how it is possible to create a delegate to a method that has less derived (contra-variant) parameter types and a more derived (covariant) return type.

The assignment to d3 shows how no conversion exists if the method is not applicable.

The assignment to d4 shows how the method must be applicable in its normal form.

The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. Thus, the example

object obj = new EventHandler(myDialog.OkClick);

could instead be written

object obj = (EventHandler)myDialog.OkClick;

Method groups may influence overload resolution, and participate in type inference. See §7.4 for further details.



The runtime evaluation of a method group conversion proceeds as follows:

  • If the method selected at compile-time is an instance method, or it is an extension method which is accessed as an instance method, the target object of the delegate is determined from the instance expression associated with E:

  • The instance expression is evaluated. If this evaluation causes an exception, no further steps are executed.

  • If the instance expression is of a reference-type, the value computed by the instance expression becomes the target object. If the target object is null, a System.NullReferenceException is thrown and no further steps are executed.

  • If the instance expression is of a value-type, a boxing operation (§4.3.1) is performed to convert the value to an object, and this object becomes the target object.

  • Otherwise the selected method is part of a static method call, and the target object of the delegate is null.

  • A new instance of the delegate type D is allocated. If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.

  • The new delegate instance is initialized with a reference to the method that was determined at compile-time and a reference to the target object computed above.


7.Expressions


An expression is a sequence of operators and operands. This chapter defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

7.1Expression classifications


An expression is classified as one of the following:

  • A value. Every value has an associated type.

  • A variable. Every variable has an associated type, namely the declared type of the variable.

  • A namespace. An expression with this classification can only appear as the left hand side of a member-access (§7.5.4). In any other context, an expression classified as a namespace causes a compile-time error.

  • A type. An expression with this classification can only appear as the left hand side of a member-access (§7.5.4), or as an operand for the as operator (§7.9.11), the is operator (§7.9.10), or the typeof operator (§7.5.11). In any other context, an expression classified as a type causes a compile-time error.

  • A method group, which is a set of overloaded methods resulting from a member lookup (§7.3). A method group may have an associated instance expression and an associated type argument list. When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by this (§7.5.7). A method group is permitted in an invocation-expression (§7.5.5) or a delegate-creation-expression (§7.5.10.5), and can be implicitly converted to a compatible delegate type (§6.6). In any other context, an expression classified as a method group causes a compile-time error.

  • A null literal. An expression with this classification can be implicitly converted to a reference type or nullable type.

  • An anonymous function. An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.

  • A property access. Every property access has an associated type, namely the type of the property. Furthermore, a property access may have an associated instance expression. When an accessor (the get or set block) of an instance property access is invoked, the result of evaluating the instance expression becomes the instance represented by this (§7.5.7).

  • An event access. Every event access has an associated type, namely the type of the event. Furthermore, an event access may have an associated instance expression. An event access may appear as the left hand operand of the += and -= operators (§7.16.3). In any other context, an expression classified as an event access causes a compile-time error.

  • An indexer access. Every indexer access has an associated type, namely the element type of the indexer. Furthermore, an indexer access has an associated instance expression and an associated argument list. When an accessor (the get or set block) of an indexer access is invoked, the result of evaluating the instance expression becomes the instance represented by this (§7.5.7), and the result of evaluating the argument list becomes the parameter list of the invocation.

  • Nothing. This occurs when the expression is an invocation of a method with a return type of void. An expression classified as nothing is only valid in the context of a statement-expression (§8.6).

The final result of an expression is never a namespace, type, method group, or event access. Rather, as noted above, these categories of expressions are intermediate constructs that are only permitted in certain contexts.

A property access or indexer access is always reclassified as a value by performing an invocation of the get-accessor or the set-accessor. The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the set-accessor is invoked to assign a new value (§7.16.1). Otherwise, the get-accessor is invoked to obtain the current value (§7.1.1).


7.1.1Values of expressions


Most of the constructs that involve an expression ultimately require the expression to denote a value. In such cases, if the actual expression denotes a namespace, a type, a method group, or nothing, a compile-time error occurs. However, if the expression denotes a property access, an indexer access, or a variable, the value of the property, indexer, or variable is implicitly substituted:

  • The value of a variable is simply the value currently stored in the storage location identified by the variable. A variable must be considered definitely assigned (§5.3) before its value can be obtained, or otherwise a compile-time error occurs.

  • The value of a property access expression is obtained by invoking the get-accessor of the property. If the property has no get-accessor, a compile-time error occurs. Otherwise, a function member invocation (§7.4.4) is performed, and the result of the invocation becomes the value of the property access expression.

  • The value of an indexer access expression is obtained by invoking the get-accessor of the indexer. If the indexer has no get-accessor, a compile-time error occurs. Otherwise, a function member invocation (§7.4.4) is performed with the argument list associated with the indexer access expression, and the result of the invocation becomes the value of the indexer access expression.


Download 3.2 Mb.

Share with your friends:
1   ...   22   23   24   25   26   27   28   29   ...   85




The database is protected by copyright ©ininet.org 2024
send message

    Main page