﻿ Better conversion from expression
﻿ КАТЕГОРИИ: Археология Биология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология

ЗНАЕТЕ ЛИ ВЫ?

# Better conversion from expression

Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if at least one of the following holds:

· E has a type S and an identity conversion exists from S to T1 but not from S to T2

· E is not an anonymous function and T1 is a better conversion target than T2 (§7.5.3.5)

· E is an anonymous function, T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2> and one of the following holds:

o D1 is a better conversion target than D2

o D1 and D2 have identical parameter lists, and one of the following holds:

· D1 has a return type Y1, and D2 has a return type Y2, an inferred return type X exists for E in the context of that parameter list (§7.5.2.12), and the conversion from X to Y1 is better than the conversion from X to Y2

· E is async, D1 has a return type Task<Y1>, and D2 has a return type Task<Y2>, an inferred return type Task<X> exists for E in the context of that parameter list (§7.5.2.12), and the conversion from X to Y1 is better than the conversion from X to Y2

· D1 has a return type Y, and D2 is void returning

Better conversion from type

Given a conversion C1 that converts from a type S to a type T1, and a conversion C2 that converts from a type S to a type T2, C1 is a better conversion than C2 if at least one of the following holds:

· An identity conversion exists from S to T1 but not from S to T2

· T1 is a better conversion target than T2 (§7.5.3.5)

Better conversion target

Given two different types T1 and T2, T1 is a better conversion target than T2 if at least one of the following holds:

· An implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists

· T1 is a signed integral type and T2 is an unsigned integral type. Specifically:

o T1 is sbyte and T2 is byte, ushort, uint, or ulong

o T1 is short and T2 is ushort, uint, or ulong

o T1 is int and T2 is uint, or ulong

o T1 is long and T2 is ulong

While signatures as declared must be unique, it is possible that substitution of type arguments results in identical signatures. In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.

The following examples show overloads that are valid and invalid according to this rule:

interface I1<T> {...}

interface I2<T> {...}

class G1<U>
{
int F1(U u); // Overload resulotion for G<int>.F1
int F1(int i); // will pick non-generic

void F2(I1<U> a); // Valid overload
void F2(I2<U> a);
}

class G2<U,V>
{
void F3(U u, V v); // Valid, but overload resolution for
void F3(V v, U u); // G2<int,int>.F3 will fail

void F4(U u, I1<V> v); // Valid, but overload resolution for
void F4(I1<V> v, U u); // G2<I1<int>,int>.F4 will fail

void F5(U u1, I1<V> v2); // Valid overload
void F5(V v1, U u2);

void F6(ref U u); // valid overload
void F6(out V v);
}

Compile-time checking of dynamic overload resolution

For most dynamically bound operations the set of possible candidates for resolution is unknown at compile-time. In certain cases, however the candidate set is known at compile-time:

· Static method calls with dynamic arguments

· Instance method calls where the receiver is not a dynamic expression

· Indexer calls where the receiver is not a dynamic expression

· Constructor calls with dynamic arguments

In these cases a limited compile-time check is performed for each candidate to see if any of them could possibly apply at run-time.This check consists of the following steps:

· Partial type inference: Any type argument that does not depend directly or indirectly on an argument of type dynamic is inferred using the rules of §7.5.2. The remaining type arguments are unknown.

· Partial applicability check: Applicability is checked according to §7.5.3.1, but ignoring parameters whose types are unknown.

If no candidate passes this test, a compile-time error occurs.

Function member invocation

This section describes the process that takes place at run-time to invoke a particular function member. It is assumed that a binding-time process has already determined the particular member to invoke, possibly by applying overload resolution to a set of candidate function members.

For purposes of describing the invocation process, function members are divided into two categories:

· Static function members. These are instance constructors, static methods, static property accessors, and user-defined operators. Static function members are always non-virtual.

· Instance function members. These are instance methods, instance property accessors, and indexer accessors. Instance function members are either non-virtual or virtual, and are always invoked on a particular instance. The instance is computed by an instance expression, and it becomes accessible within the function member as this (§7.6.7).

The run-time processing of a function member invocation consists of the following steps, where M is the function member and, if M is an instance member, E is the instance expression:

· If M is a static function member:

o The argument list is evaluated as described in §7.5.1.

o M is invoked.

· If M is an instance function member declared in a value-type:

o E is evaluated. If this evaluation causes an exception, then no further steps are executed.

o If E is not classified as a variable, then a temporary local variable of E’s type is created and the value of E is assigned to that variable. E is then reclassified as a reference to that temporary local variable. The temporary variable is accessible as this within M, but not in any other way. Thus, only when E is a true variable is it possible for the caller to observe the changes that M makes to this.

o The argument list is evaluated as described in §7.5.1.

o M is invoked. The variable referenced by E becomes the variable referenced by this.

· If M is an instance function member declared in a reference-type:

o E is evaluated. If this evaluation causes an exception, then no further steps are executed.

o The argument list is evaluated as described in §7.5.1.

o If the type of E is a value-type, a boxing conversion (§4.3.1) is performed to convert E to type object, and E is considered to be of type object in the following steps. In this case, M could only be a member of System.Object.

o The value of E is checked to be valid. If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.

o The function member implementation to invoke is determined:

· If the binding-time type of E is an interface, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. This function member is determined by applying the interface mapping rules (§13.4.4) to determine the implementation of M provided by the run-time type of the instance referenced by E.

· Otherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. This function member is determined by applying the rules for determining the most derived implementation (§10.6.3) of M with respect to the run-time type of the instance referenced by E.

· Otherwise, M is a non-virtual function member, and the function member to invoke is M itself.

o The function member implementation determined in the step above is invoked. The object referenced by E becomes the object referenced by this.

﻿

Последнее изменение этой страницы: 2016-12-14; Нарушение авторского права страницы

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