ConversionesConversions

Un conversión permite que una expresión se traten como de un tipo determinado.A conversion enables an expression to be treated as being of a particular type. Una conversión puede producir una expresión de un tipo determinado se traten como si tuviera un tipo diferente, o puede hacer que una expresión sin un tipo que se va a obtener un tipo.A conversion may cause an expression of a given type to be treated as having a different type, or it may cause an expression without a type to get a type. Las conversiones pueden ser implícita o explícita, y esto determina si se requiere una conversión explícita.Conversions can be implicit or explicit, and this determines whether an explicit cast is required. Por ejemplo, la conversión del tipo int escriba long es implícito, es así expresiones de tipo int implícitamente se pueden tratar como tipo long.For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. La conversión opuesta, del tipo long escriba int, es explícita, por lo que se requiere una conversión explícita.The opposite conversion, from type long to type int, is explicit and so an explicit cast is required.

int a = 123;
long b = a;         // implicit conversion from int to long
int c = (int) b;    // explicit conversion from long to int

Algunas conversiones se definen mediante el lenguaje.Some conversions are defined by the language. Los programas también pueden definir sus propias conversiones (conversiones definidas por el usuario).Programs may also define their own conversions (User-defined conversions).

Conversiones implícitasImplicit conversions

Las conversiones siguientes se clasifican como conversiones implícitas:The following conversions are classified as implicit conversions:

  • Conversiones de identidadIdentity conversions
  • Conversiones numéricas implícitasImplicit numeric conversions
  • Conversiones implícitas de enumeración.Implicit enumeration conversions.
  • Conversiones implícitas que acepta valores nullImplicit nullable conversions
  • Conversiones de literal nullNull literal conversions
  • Conversiones implícitas de referenciaImplicit reference conversions
  • Conversiones boxingBoxing conversions
  • Conversiones implícitas de dinámicasImplicit dynamic conversions
  • Conversiones implícitas de expresión constanteImplicit constant expression conversions
  • Conversiones implícitas definido por el usuarioUser-defined implicit conversions
  • Conversiones de función anónimaAnonymous function conversions
  • Conversiones de métodos de grupoMethod group conversions

Conversiones implícitas pueden ocurrir en una variedad de situaciones, incluidas las llamadas a funciones miembro (comprobación de la resolución de sobrecarga dinámicas de tiempo de compilación), las expresiones de conversión (expresiones de conversión), y las asignaciones (operadores de asignación).Implicit conversions can occur in a variety of situations, including function member invocations (Compile-time checking of dynamic overload resolution), cast expressions (Cast expressions), and assignments (Assignment operators).

Las conversiones implícitas predefinidas siempre se ejecuta correctamente y nunca causan que se produzcan excepciones.The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. Las conversiones implícitas diseñadas correctamente definido por el usuario deben presentar estas características también.Properly designed user-defined implicit conversions should exhibit these characteristics as well.

Para los fines de conversión, los tipos de object y dynamic se consideran equivalentes.For the purposes of conversion, the types object and dynamic are considered equivalent.

Sin embargo, las conversiones dinámicas (conversiones implícitas de dinámicas y las conversiones explícitas de dinámicas) solo se aplican a expresiones de tipo dynamic (el tipo dinámico).However, dynamic conversions (Implicit dynamic conversions and Explicit dynamic conversions) apply only to expressions of type dynamic (The dynamic type).

Conversión de identidadIdentity conversion

Convierte una conversión de identidad de cualquier tipo en el mismo tipo.An identity conversion converts from any type to the same type. Esta conversión existe de forma que se puede decir una entidad que ya tiene un tipo necesario se pueda convertir a ese tipo.This conversion exists such that an entity that already has a required type can be said to be convertible to that type.

  • Dado que object y dynamic se consideran equivalentes que hay una conversión de identidad entre object y dynamicy entre tipos construidos que son iguales cuando se reemplaza todas las apariciones de dynamic con object.Because object and dynamic are considered equivalent there is an identity conversion between object and dynamic, and between constructed types that are the same when replacing all occurrences of dynamic with object.

Conversiones numéricas implícitasImplicit numeric conversions

Las conversiones numéricas implícitas son:The implicit numeric conversions are:

  • Desde sbyte a short, int, long, float, double, o decimal.From sbyte to short, int, long, float, double, or decimal.
  • Desde byte a short, ushort, int, uint, long, ulong, float, double, o decimal.From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • Desde short a int, long, float, double, o decimal.From short to int, long, float, double, or decimal.
  • Desde ushort a int, uint, long, ulong, float, double, o decimal.From ushort to int, uint, long, ulong, float, double, or decimal.
  • Desde int a long, float, double, o decimal.From int to long, float, double, or decimal.
  • Desde uint a long, ulong, float, double, o decimal.From uint to long, ulong, float, double, or decimal.
  • Desde long a float, double, o decimal.From long to float, double, or decimal.
  • Desde ulong a float, double, o decimal.From ulong to float, double, or decimal.
  • Desde char a ushort, int, uint, long, ulong, float, double, o decimal.From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • Desde float a double.From float to double.

Conversiones de int, uint, long, o ulong a float y desde long o ulong a double puede provocar una pérdida de precisión, pero no una pérdida de magnitud.Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss of precision, but will never cause a loss of magnitude. Las conversiones numéricas implícitas nunca pierden información.The other implicit numeric conversions never lose any information.

No hay ninguna conversión implícita para el char escriba, por lo que los valores de los otros tipos enteros no se convierten automáticamente en el char tipo.There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.

Conversiones implícitas de enumeraciónImplicit enumeration conversions

Permite una conversión implícita de enumeración el decimal_integer_literal 0 convertirse a cualquier enum_type y a cualquier nullable_type cuyo el tipo subyacente es un enum_type.An implicit enumeration conversion permits the decimal_integer_literal 0 to be converted to any enum_type and to any nullable_type whose underlying type is an enum_type. En este caso, la conversión se evalúa mediante la conversión subyacente enum_type y ajuste el resultado (tipos que aceptan valores NULL).In the latter case the conversion is evaluated by converting to the underlying enum_type and wrapping the result (Nullable types).

Conversiones implícitas de cadena interpoladaImplicit interpolated string conversions

Implicit interpoladas cadena conversión permite un interpolated_string_expression (cadenas interpoladas) va a convertir en System.IFormattable o System.FormattableString (que implementa System.IFormattable).An implicit interpolated string conversion permits an interpolated_string_expression (Interpolated strings) to be converted to System.IFormattable or System.FormattableString (which implements System.IFormattable).

Cuando esta conversión se aplica un valor de cadena no está compuesto por la cadena interpolada.When this conversion is applied a string value is not composed from the interpolated string. En su lugar una instancia de System.FormattableString está creado, tal como se describe en cadenas interpoladas.Instead an instance of System.FormattableString is created, as further described in Interpolated strings.

Conversiones implícitas que acepta valores nullImplicit nullable conversions

Las conversiones implícitas predefinidas que funcionan en tipos de valor distinto de NULL también pueden utilizarse con los formularios de esos tipos que aceptan valores NULL.Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. Para cada identidad implícita predefinida y las conversiones numéricas que conversión de un tipo de valor distinto de NULL S a un tipo de valor distinto de NULL T, existen las siguientes conversiones implícitas que acepta valores NULL:For each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:

  • Una conversión implícita de S? a T?.An implicit conversion from S? to T?.
  • Una conversión implícita de S a T?.An implicit conversion from S to T?.

Evaluación de una conversión implícita que acepta valores NULL en función de una conversión subyacente de S a T continúa como sigue:Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Si la conversión que acepta valores NULL es desde S? a T?:If the nullable conversion is from S? to T?:

    • Si el valor de origen es null (HasValue propiedad es false), el resultado es el valor null del tipo T?.If the source value is null (HasValue property is false), the result is the null value of type T?.
    • En caso contrario, la conversión se evalúa como un desajuste de S? a S, seguido de la conversión subyacente de S a T, seguido de un ajuste (tipos que aceptan valores NULL) desde T a T?.Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (Nullable types) from T to T?.
  • Si la conversión que acepta valores NULL es desde S a T?, la conversión se evalúa como la conversión subyacente de S a T seguida de un ajuste de T a T?.If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.

Conversiones de literal nullNull literal conversions

Existe una conversión implícita desde el null literal a cualquier tipo que acepta valores NULL.An implicit conversion exists from the null literal to any nullable type. Esta conversión genera el valor null (tipos que aceptan valores NULL) del tipo que acepta valores NULL especificado.This conversion produces the null value (Nullable types) of the given nullable type.

Conversiones implícitas de referenciaImplicit reference conversions

Las conversiones implícitas de referencia son:The implicit reference conversions are:

  • Desde cualquier reference_type a object y dynamic.From any reference_type to object and dynamic.
  • Desde cualquier class_type S a cualquier class_type T, que proporciona S se deriva de T.From any class_type S to any class_type T, provided S is derived from T.
  • Desde cualquier class_type S a cualquier interface_type T, que proporciona S implementa T.From any class_type S to any interface_type T, provided S implements T.
  • Desde cualquier interface_type S a cualquier interface_type T, que proporciona S se deriva de T.From any interface_type S to any interface_type T, provided S is derived from T.
  • Desde un array_type S con un tipo de elemento SE a un array_type T con un tipo de elemento TE, siempre que todos los elementos siguientes son verdaderas:From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • S y T difieren solo en el tipo de elemento.S and T differ only in element type. En otras palabras, S y T tienen el mismo número de dimensiones.In other words, S and T have the same number of dimensions.
    • Ambos SE y TE son reference_types.Both SE and TE are reference_types.
    • Existe una conversión implícita de referencia de SE a TE.An implicit reference conversion exists from SE to TE.
  • Desde cualquier array_type a System.Array y las interfaces que implementa.From any array_type to System.Array and the interfaces it implements.
  • Desde un tipo de matriz unidimensional S[] a System.Collections.Generic.IList<T> y sus interfaces base, proporcionadas que hay una conversión implícita de referencia o identidad de S a T.From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an implicit identity or reference conversion from S to T.
  • Desde cualquier delegate_type a System.Delegate y las interfaces que implementa.From any delegate_type to System.Delegate and the interfaces it implements.
  • Desde el literal null para alguna reference_type.From the null literal to any reference_type.
  • Desde cualquier reference_type a un reference_type T si tiene una conversión implícita de identidad o una referencia a un reference_type T0 y T0 tiene una conversión de identidad a T.From any reference_type to a reference_type T if it has an implicit identity or reference conversion to a reference_type T0 and T0 has an identity conversion to T.
  • Desde cualquier reference_type a un tipo de interfaz o delegado T si tiene una conversión implícita de identidad o una referencia a un tipo de interfaz o delegado T0 y T0 es convertible de varianza ( Conversión de varianza) a T.From any reference_type to an interface or delegate type T if it has an implicit identity or reference conversion to an interface or delegate type T0 and T0 is variance-convertible (Variance conversion) to T.
  • Conversiones implícitas que implica parámetros de tipo que se sabe que son tipos de referencia.Implicit conversions involving type parameters that are known to be reference types. Consulte conversiones implícitas que implica parámetros de tipo para obtener más detalles sobre las conversiones implícitas que implica parámetros de tipo.See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

Las conversiones implícitas de referencia son aquellas conversiones entre reference_types que se pueda demostrar que siempre se realizan correctamente y, por lo tanto, no requieren comprobaciones en tiempo de ejecución.The implicit reference conversions are those conversions between reference_types that can be proven to always succeed, and therefore require no checks at run-time.

Las conversiones de referencia, implícitas o explícitas, nunca cambian la identidad referencial del objeto que se va a convertir.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. En otras palabras, mientras que una conversión de referencia puede cambiar el tipo de la referencia, nunca cambia el tipo o valor del objeto que hace referencia.In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

Conversiones boxingBoxing conversions

Una conversión boxing permite un value_type convertir implícitamente a un tipo de referencia.A boxing conversion permits a value_type to be implicitly converted to a reference type. Existe una conversión boxing de cualquier non_nullable_value_type a object y dynamica System.ValueType y a cualquier interface_type implementado por el non_ nullable_value_type.A boxing conversion exists from any non_nullable_value_type to object and dynamic, to System.ValueType and to any interface_type implemented by the non_nullable_value_type. Además un enum_type puede convertirse al tipo System.Enum.Furthermore an enum_type can be converted to the type System.Enum.

Existe una conversión boxing de un nullable_type a un tipo de referencia, si y solo si una conversión boxing existe subyacente non_nullable_value_type al tipo de referencia.A boxing conversion exists from a nullable_type to a reference type, if and only if a boxing conversion exists from the underlying non_nullable_value_type to the reference type.

Un tipo de valor tiene una conversión boxing a un tipo de interfaz I si tiene una conversión boxing a un tipo de interfaz I0 y I0 tiene una conversión de identidad a I.A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface type I0 and I0 has an identity conversion to I.

Un tipo de valor tiene una conversión boxing a un tipo de interfaz I si tiene una conversión boxing a un tipo de interfaz o delegado I0 y I0 es convertible de varianza (conversión de varianza) a I.A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface or delegate type I0 and I0 is variance-convertible (Variance conversion) to I.

Conversión boxing de un valor de un non_nullable_value_type consiste en asignar una instancia del objeto y copiar el value_type valor en esa instancia.Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. Un struct puede realizar la conversión boxing al tipo System.ValueType, ya que es una clase base para todas las estructuras (herencia).A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

Conversión boxing de un valor de un nullable_type continúa como sigue:Boxing a value of a nullable_type proceeds as follows:

  • Si el valor de origen es null (HasValue propiedad es false), el resultado es una referencia nula del tipo de destino.If the source value is null (HasValue property is false), the result is a null reference of the target type.
  • En caso contrario, el resultado es una referencia a una conversión boxing T producidos por boxing el valor de origen y la acción de desencapsular.Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

Se describe más detalladamente en las conversiones boxing conversiones Boxing.Boxing conversions are described further in Boxing conversions.

Conversiones implícitas de dinámicasImplicit dynamic conversions

Existe una conversión implícita de dinámica de una expresión de tipo dynamic a cualquier tipo T.An implicit dynamic conversion exists from an expression of type dynamic to any type T. La conversión se enlaza dinámicamente (enlace dinámico), lo que significa que se buscará una conversión implícita en tiempo de ejecución desde el tipo de tiempo de ejecución de la expresión T.The conversion is dynamically bound (Dynamic binding), which means that an implicit conversion will be sought at run-time from the run-time type of the expression to T. Si no se encuentra ninguna conversión, se produce una excepción en tiempo de ejecución.If no conversion is found, a run-time exception is thrown.

Tenga en cuenta que esta conversión implícita aparentemente infringe el Consejo al principio de conversiones implícitas que una conversión implícita nunca debe producir una excepción.Note that this implicit conversion seemingly violates the advice in the beginning of Implicit conversions that an implicit conversion should never cause an exception. Sin embargo no es la conversión, pero la buscar de la conversión que produce la excepción.However it is not the conversion itself, but the finding of the conversion that causes the exception. El riesgo de las excepciones de tiempo de ejecución es inherente en el uso de enlace dinámico.The risk of run-time exceptions is inherent in the use of dynamic binding. Si el enlace dinámico de la conversión no es el deseado, la expresión se puede convertir en primer lugar a objecty, a continuación, al tipo deseado.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

El ejemplo siguiente muestra las conversiones implícitas de dinámicas:The following example illustrates implicit dynamic conversions:

object o  = "object"
dynamic d = "dynamic";

string s1 = o; // Fails at compile-time -- no conversion exists
string s2 = d; // Compiles and succeeds at run-time
int i     = d; // Compiles but fails at run-time -- no conversion exists

Las asignaciones a s2 y i ambos emplean las conversiones implícitas dinámicas, donde se suspende el enlace de las operaciones hasta el tiempo de ejecución.The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. En tiempo de ejecución, se buscan las conversiones implícitas del tipo de tiempo de ejecución de d -- string --al tipo de destino.At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. Se encuentra una conversión a string pero no a int.A conversion is found to string but not to int.

Conversiones implícitas de expresión constanteImplicit constant expression conversions

Una conversión implícita de expresión constante permite las siguientes conversiones:An implicit constant expression conversion permits the following conversions:

  • Un constant_expression (expresiones constantes) de tipo int puede convertirse al tipo sbyte, byte, short, ushort, uint, o ulong, siempre que el valor de la constant_expression está dentro del intervalo del tipo de destino.A constant_expression (Constant expressions) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant_expression is within the range of the destination type.
  • Un constant_expression typu long puede convertirse al tipo ulong, siempre que el valor de la constant_expression no es negativo.A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

Conversiones implícitas que implica parámetros de tipoImplicit conversions involving type parameters

Existen las siguientes conversiones implícitas para un parámetro de tipo dado T:The following implicit conversions exist for a given type parameter T:

  • Desde T a su clase base eficaz C, desde T a cualquier clase base de Cy desde T a cualquier interfaz implementada por C.From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. En caso contrario, la conversión se ejecuta como una conversión implícita de referencia o una conversión de identidad.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Desde T a un tipo de interfaz I en Tdel conjunto de interfaces efectivas y desde T a cualquier interfaz base de I.From T to an interface type I in T's effective interface set and from T to any base interface of I. En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. En caso contrario, la conversión se ejecuta como una conversión implícita de referencia o una conversión de identidad.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Desde T a un parámetro de tipo U, que proporciona T depende U (restricciones de parámetro de tipo).From T to a type parameter U, provided T depends on U (Type parameter constraints). En tiempo de ejecución, si U es un tipo de valor, a continuación, T y U son necesariamente del mismo tipo y se realiza ninguna conversión.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. De lo contrario, si T es un tipo de valor, la conversión se ejecuta como una conversión boxing.Otherwise, if T is a value type, the conversion is executed as a boxing conversion. En caso contrario, la conversión se ejecuta como una conversión implícita de referencia o una conversión de identidad.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Desde el literal null a T, que proporciona T se sabe que es un tipo de referencia.From the null literal to T, provided T is known to be a reference type.
  • Desde T a un tipo de referencia I si tiene una conversión implícita a un tipo de referencia S0 y S0 tiene una conversión de identidad a S.From T to a reference type I if it has an implicit conversion to a reference type S0 and S0 has an identity conversion to S. En tiempo de ejecución, la conversión se ejecuta la misma manera que la conversión a S0.At run-time the conversion is executed the same way as the conversion to S0.
  • Desde T a un tipo de interfaz I si tiene una conversión implícita a un tipo de interfaz o delegado I0 y I0 es convertible de varianza a I (conversión de varianza ).From T to an interface type I if it has an implicit conversion to an interface or delegate type I0 and I0 is variance-convertible to I (Variance conversion). En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. En caso contrario, la conversión se ejecuta como una conversión implícita de referencia o una conversión de identidad.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

Si T se sabe que es un tipo de referencia (restricciones de parámetro de tipo), las conversiones anteriores se clasifican como conversiones implícitas de referencia (conversiones implícitas de referencia).If T is known to be a reference type (Type parameter constraints), the conversions above are all classified as implicit reference conversions (Implicit reference conversions). Si T no es sabe que un tipo de referencia, las conversiones anteriores se clasifican como conversiones boxing (conversiones Boxing).If T is not known to be a reference type, the conversions above are classified as boxing conversions (Boxing conversions).

Conversiones implícitas definido por el usuarioUser-defined implicit conversions

Una conversión implícita definido por el usuario consta de una conversión implícita opcional estándar, seguida por la ejecución de un operador de conversión implícito definido por el usuario, seguido de otra conversión implícita opcional estándar.A user-defined implicit conversion consists of an optional standard implicit conversion, followed by execution of a user-defined implicit conversion operator, followed by another optional standard implicit conversion. Las reglas exactas para evaluar las conversiones implícitas definido por el usuario se describen en de procesamiento de las conversiones implícitas definido por el usuario.The exact rules for evaluating user-defined implicit conversions are described in Processing of user-defined implicit conversions.

Conversiones de función anónima y conversiones de métodos de grupoAnonymous function conversions and method group conversions

Funciones anónimas y grupos de métodos no tienen tipos de por sí mismos, pero se pueden convertir implícitamente para delegar tipos o tipos de árbol de expresión.Anonymous functions and method groups do not have types in and of themselves, but may be implicitly converted to delegate types or expression tree types. Conversiones de función anónima se describen con más detalle en conversiones de función anónima y conversiones de grupo de métodos en conversiones de métodos de grupo.Anonymous function conversions are described in more detail in Anonymous function conversions and method group conversions in Method group conversions.

Conversiones explícitasExplicit conversions

Las conversiones siguientes se clasifican como las conversiones explícitas:The following conversions are classified as explicit conversions:

  • Todas las conversiones implícitas.All implicit conversions.
  • Conversiones numéricas explícitas.Explicit numeric conversions.
  • Conversiones explícitas de enumeración.Explicit enumeration conversions.
  • Conversiones explícitas que acepta valores NULL.Explicit nullable conversions.
  • Conversiones explícitas de referencia.Explicit reference conversions.
  • Conversiones de interfaz explícita.Explicit interface conversions.
  • Conversiones unboxing.Unboxing conversions.
  • Conversiones explícitas de dinámicasExplicit dynamic conversions
  • Conversiones explícitas definidas por el usuario.User-defined explicit conversions.

Las conversiones explícitas pueden producirse en expresiones de conversión (expresiones de conversión).Explicit conversions can occur in cast expressions (Cast expressions).

El conjunto de conversiones explícitas incluye todas las conversiones implícitas.The set of explicit conversions includes all implicit conversions. Esto significa que se permiten expresiones de conversión redundantes.This means that redundant cast expressions are allowed.

Las conversiones explícitas que no son las conversiones implícitas son las conversiones que no se puede demostrar que siempre se realizan correctamente, las conversiones que se sabe que posiblemente se pierde información y las conversiones en dominios de tipos lo suficientemente diferentes para ameritar explícita notación.The explicit conversions that are not implicit conversions are conversions that cannot be proven to always succeed, conversions that are known to possibly lose information, and conversions across domains of types sufficiently different to merit explicit notation.

Conversiones numéricas explícitasExplicit numeric conversions

Las conversiones numéricas explícitas son las conversiones de un numeric_type a otro numeric_type para que una conversión numérica implícita (deconversionesnuméricasimplícitas) aún no existe:The explicit numeric conversions are the conversions from a numeric_type to another numeric_type for which an implicit numeric conversion (Implicit numeric conversions) does not already exist:

  • Desde sbyte a byte, ushort, uint, ulong, o char.From sbyte to byte, ushort, uint, ulong, or char.
  • Desde byte a sbyte y char.From byte to sbyte and char.
  • Desde short a sbyte, byte, ushort, uint, ulong, o char.From short to sbyte, byte, ushort, uint, ulong, or char.
  • Desde ushort a sbyte, byte, short, o char.From ushort to sbyte, byte, short, or char.
  • Desde int a sbyte, byte, short, ushort, uint, ulong, o char.From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • Desde uint a sbyte, byte, short, ushort, int, o char.From uint to sbyte, byte, short, ushort, int, or char.
  • Desde long a sbyte, byte, short, ushort, int, uint, ulong, o char.From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • Desde ulong a sbyte, byte, short, ushort, int, uint, long, o char.From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • Desde char a sbyte, byte, o short.From char to sbyte, byte, or short.
  • Desde float a sbyte, byte, short, ushort, int, uint, long, ulong, char, o decimal.From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • Desde double a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, o decimal.From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • Desde decimal a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, o double.From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

Dado que las conversiones explícitas incluyen todas las conversiones numéricas implícitas y explícitas, siempre es posible convertir desde cualquier numeric_type a cualquier otro numeric_type mediante una expresión de conversión () Expresiones de conversión).Because the explicit conversions include all implicit and explicit numeric conversions, it is always possible to convert from any numeric_type to any other numeric_type using a cast expression (Cast expressions).

Las conversiones numéricas explícitas producir pérdida de información o incluso producen que se produzcan excepciones.The explicit numeric conversions possibly lose information or possibly cause exceptions to be thrown. Una conversión numérica explícita se procesa como sigue:An explicit numeric conversion is processed as follows:

  • Para una conversión de un tipo integral a otro tipo entero, el procesamiento depende del contexto de comprobación de desbordamiento (los operadores checked y unchecked) en que se toma la conversión colocar:For a conversion from an integral type to another integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • En un checked contexto, la conversión se realiza correctamente si el valor del operando de origen está dentro del intervalo del tipo de destino, pero inicia una System.OverflowException si el valor del operando de origen está fuera del intervalo del tipo de destino.In a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws a System.OverflowException if the value of the source operand is outside the range of the destination type.
    • En un unchecked contexto, la conversión siempre se realiza correctamente y continúa como sigue.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Si el tipo de origen es mayor que el tipo de destino, el valor de origen se trunca al descartar sus bits "extra" más significativos.If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. El resultado se trata como un valor del tipo de destino.The result is then treated as a value of the destination type.
      • Si el tipo de origen es menor que el tipo de destino, el valor de origen se amplía mediante signos o ceros para que tenga el mismo tamaño que el tipo de destino.If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it is the same size as the destination type. La ampliación mediante signos se usa si el tipo de origen tiene signo; se emplea ampliación mediante ceros si el tipo de origen no tiene signo.Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. El resultado se trata como un valor del tipo de destino.The result is then treated as a value of the destination type.
      • Si el tipo de origen es del mismo tamaño que el tipo de destino, el valor de origen se trata como un valor del tipo de destino.If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
  • Para una conversión de decimal a un tipo entero, el valor de origen se redondea hacia cero al valor entero más cercano, y este valor entero se convierte en el resultado de la conversión.For a conversion from decimal to an integral type, the source value is rounded towards zero to the nearest integral value, and this integral value becomes the result of the conversion. Si el valor entero resultante está fuera del intervalo del tipo de destino, un System.OverflowException se produce.If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • Para una conversión de float o double a un tipo entero, el procesamiento depende del contexto de comprobación de desbordamiento (los operadores checked y unchecked) en que se toma la conversión colocar:For a conversion from float or double to an integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • En un checked contexto, la conversión continúa como sigue:In a checked context, the conversion proceeds as follows:
      • Si el valor del operando es NaN o infinito, un System.OverflowException se produce.If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
      • En caso contrario, el operando de origen se redondea hacia cero al valor entero más cercano.Otherwise, the source operand is rounded towards zero to the nearest integral value. Si este valor entero está dentro del intervalo del tipo de destino, a continuación, este valor es el resultado de la conversión.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • De lo contrario, se produce una excepción System.OverflowException.Otherwise, a System.OverflowException is thrown.
    • En un unchecked contexto, la conversión siempre se realiza correctamente y continúa como sigue.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Si el valor del operando es NaN o infinito, el resultado de la conversión es un valor no especificado del tipo de destino.If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
      • En caso contrario, el operando de origen se redondea hacia cero al valor entero más cercano.Otherwise, the source operand is rounded towards zero to the nearest integral value. Si este valor entero está dentro del intervalo del tipo de destino, a continuación, este valor es el resultado de la conversión.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • En caso contrario, el resultado de la conversión es un valor no especificado del tipo de destino.Otherwise, the result of the conversion is an unspecified value of the destination type.
  • Para una conversión de double a float, double valor se redondea al más cercano float valor.For a conversion from double to float, the double value is rounded to the nearest float value. Si el double valor es demasiado pequeño para representarse como un float, el resultado se convierte en cero positivo o cero negativo.If the double value is too small to represent as a float, the result becomes positive zero or negative zero. Si el double valor es demasiado grande para representarse como un float, el resultado es infinito positivo o infinito negativo.If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. Si el double valor es NaN, el resultado también es NaN.If the double value is NaN, the result is also NaN.
  • Para una conversión de float o double a decimal, el valor de origen se convierte en decimal representación y redondea al número más cercano después de la posición decimal 28 si es necesario (el tipo decimal).For a conversion from float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required (The decimal type). Si el valor de origen es demasiado pequeño para representarse como un decimal, el resultado se convierte en cero.If the source value is too small to represent as a decimal, the result becomes zero. Si el valor de origen es NaN, infinito o demasiado grande para representarse como un decimal, un System.OverflowException se produce.If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • Para una conversión de decimal a float o double, decimal valor se redondea al más cercano double o float valor.For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. Aunque esta conversión puede perder precisión, nunca hace que se produzca una excepción.While this conversion may lose precision, it never causes an exception to be thrown.

Conversiones explícitas de enumeraciónExplicit enumeration conversions

Las conversiones explícitas de enumeración son:The explicit enumeration conversions are:

  • Desde sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, o decimal a cualquier enum_type.From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
  • Desde cualquier enum_type a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, o decimal.From any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
  • Desde cualquier enum_type a cualquier otro enum_type.From any enum_type to any other enum_type.

Una conversión explícita de enumeración entre dos tipos se procesa al tratar cualquier participan enum_type como el tipo subyacente de la que enum_typea continuación, realiza un implícita o explícita conversión numérica entre los tipos resultantes.An explicit enumeration conversion between two types is processed by treating any participating enum_type as the underlying type of that enum_type, and then performing an implicit or explicit numeric conversion between the resulting types. Por ejemplo, dada una enum_type E con y el tipo subyacente de int, una conversión de E a byte se procesa como una conversión numérica explícita (Explicit conversiones numéricas) desde int a bytey una conversión de byte a E se procesa como una conversión numérica implícita (deconversionesnuméricasimplícitas) desde byte a int.For example, given an enum_type E with and underlying type of int, a conversion from E to byte is processed as an explicit numeric conversion (Explicit numeric conversions) from int to byte, and a conversion from byte to E is processed as an implicit numeric conversion (Implicit numeric conversions) from byte to int.

Conversiones explícitas que acepta valores nullExplicit nullable conversions

Las conversiones que aceptan valores NULL explícitas predefinidos de permitir las conversiones explícitas que funcionan en tipos de valor distinto de NULL para utilizarse también con los formularios de esos tipos que aceptan valores NULL.Explicit nullable conversions permit predefined explicit conversions that operate on non-nullable value types to also be used with nullable forms of those types. Para cada una de las conversiones explícitas predefinidas que convierten de un tipo de valor distinto de NULL S a un tipo de valor distinto de NULL T (conversión de identidad, deconversionesnuméricasimplícitas, Conversiones implícitas de enumeración, conversiones numéricas explícitas, y conversiones explícitas de enumeración), lo siguiente Existen las conversiones que aceptan valores NULL:For each of the predefined explicit conversions that convert from a non-nullable value type S to a non-nullable value type T (Identity conversion, Implicit numeric conversions, Implicit enumeration conversions, Explicit numeric conversions, and Explicit enumeration conversions), the following nullable conversions exist:

  • Una conversión explícita de S? a T?.An explicit conversion from S? to T?.
  • Una conversión explícita de S a T?.An explicit conversion from S to T?.
  • Una conversión explícita de S? a T.An explicit conversion from S? to T.

Evaluación de una conversión que acepta valores NULL en función de una conversión subyacente de S a T continúa como sigue:Evaluation of a nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Si la conversión que acepta valores NULL es desde S? a T?:If the nullable conversion is from S? to T?:
    • Si el valor de origen es null (HasValue propiedad es false), el resultado es el valor null del tipo T?.If the source value is null (HasValue property is false), the result is the null value of type T?.
    • En caso contrario, la conversión se evalúa como un desajuste de S? a S, seguido de la conversión subyacente de S a T, seguido de un ajuste de T a T?.Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping from T to T?.
  • Si la conversión que acepta valores NULL es desde S a T?, la conversión se evalúa como la conversión subyacente de S a T seguida de un ajuste de T a T?.If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.
  • Si la conversión que acepta valores NULL es desde S? a T, la conversión se evalúa como un desajuste de S? a S seguido de la conversión subyacente de S a T.If the nullable conversion is from S? to T, the conversion is evaluated as an unwrapping from S? to S followed by the underlying conversion from S to T.

Tenga en cuenta que un intento para desempaquetar un valor que acepta valores NULL producirá una excepción si el valor es null.Note that an attempt to unwrap a nullable value will throw an exception if the value is null.

Conversiones explícitas de referenciaExplicit reference conversions

Las conversiones explícitas de referencia son:The explicit reference conversions are:

  • Desde object y dynamic a cualquier otro reference_type.From object and dynamic to any other reference_type.
  • Desde cualquier class_type S a cualquier class_type T, que proporciona S es una clase base de T.From any class_type S to any class_type T, provided S is a base class of T.
  • Desde cualquier class_type S a cualquier interface_type T, que proporciona S no está sellado y proporciona S no implementa T.From any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
  • Desde cualquier interface_type S a cualquier class_type T, que proporciona T no está sellado o proporcionado T implementa S.From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • Desde cualquier interface_type S a cualquier interface_type T, que proporciona S no se deriva T.From any interface_type S to any interface_type T, provided S is not derived from T.
  • Desde un array_type S con un tipo de elemento SE a un array_type T con un tipo de elemento TE, siempre que todos los elementos siguientes son verdaderas:From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • S y T difieren solo en el tipo de elemento.S and T differ only in element type. En otras palabras, S y T tienen el mismo número de dimensiones.In other words, S and T have the same number of dimensions.
    • Ambos SE y TE son reference_types.Both SE and TE are reference_types.
    • Existe una conversión explícita de referencia de SE a TE.An explicit reference conversion exists from SE to TE.
  • Desde System.Array y las interfaces que implementa a cualquier array_type.From System.Array and the interfaces it implements to any array_type.
  • Desde un tipo de matriz unidimensional S[] a System.Collections.Generic.IList<T> y sus interfaces base, siempre que una conversión explícita de referencia de S a T.From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an explicit reference conversion from S to T.
  • Desde System.Collections.Generic.IList<S> y sus interfaces base a un tipo de matriz unidimensional T[], siempre que hay una conversión explícita de referencia o identidad de S a T.From System.Collections.Generic.IList<S> and its base interfaces to a single-dimensional array type T[], provided that there is an explicit identity or reference conversion from S to T.
  • Desde System.Delegate y las interfaces que implementa a cualquier delegate_type.From System.Delegate and the interfaces it implements to any delegate_type.
  • Un tipo de referencia a un tipo de referencia T si tiene una conversión de referencia explícita a un tipo de referencia T0 y T0 tiene una conversión de identidad T.From a reference type to a reference type T if it has an explicit reference conversion to a reference type T0 and T0 has an identity conversion T.
  • Un tipo de referencia a un tipo de interfaz o delegado T si tiene una conversión de referencia explícita a un tipo de interfaz o delegado T0 y T0 es convertible de varianza a T o T es convertir a varianza T0 (conversión de varianza).From a reference type to an interface or delegate type T if it has an explicit reference conversion to an interface or delegate type T0 and either T0 is variance-convertible to T or T is variance-convertible to T0 (Variance conversion).
  • Desde D<S1...Sn> a D<T1...Tn> donde D<X1...Xn> es un tipo de delegado genérico, D<S1...Sn> no es compatible con o idénticos a D<T1...Tn>y para cada parámetro de tipo Xi de D contiene la siguiente:From D<S1...Sn> to D<T1...Tn> where D<X1...Xn> is a generic delegate type, D<S1...Sn> is not compatible with or identical to D<T1...Tn>, and for each type parameter Xi of D the following holds:
    • Si Xi es invariable, a continuación, Si es idéntico a Ti.If Xi is invariant, then Si is identical to Ti.
    • Si Xi es covariante, a continuación, hay una conversión de referencia o identidad implícita o explícita desde Si a Ti.If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
    • Si Xi es contravariante, a continuación, Si y Ti son idénticos o ambos tipos de referencia.If Xi is contravariant, then Si and Ti are either identical or both reference types.
  • Conversiones explícitas que implica parámetros de tipo que se sabe que son tipos de referencia.Explicit conversions involving type parameters that are known to be reference types. Para obtener más información sobre las conversiones explícitas que implica parámetros de tipo, consulte las conversiones explícitas que implica parámetros de tipo.For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

Las conversiones explícitas de referencia son aquellas conversiones entre tipos de referencia que requieren comprobaciones en tiempo de ejecución para garantizar que son correctos.The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

Para que una conversión de referencia explícita sea correcta en tiempo de ejecución, el valor del operando de origen debe ser null, o el tipo real del objeto al que hace referencia el operando de origen debe ser un tipo que pueda convertirse al tipo de destino mediante una referencia implícita conversión (conversiones implícitas de referencia) o una conversión boxing (conversiones Boxing).For an explicit reference conversion to succeed at run-time, the value of the source operand must be null, or the actual type of the object referenced by the source operand must be a type that can be converted to the destination type by an implicit reference conversion (Implicit reference conversions) or boxing conversion (Boxing conversions). Si se produce un error en una conversión explícita de referencia, un System.InvalidCastException se produce.If an explicit reference conversion fails, a System.InvalidCastException is thrown.

Las conversiones de referencia, implícitas o explícitas, nunca cambian la identidad referencial del objeto que se va a convertir.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. En otras palabras, mientras que una conversión de referencia puede cambiar el tipo de la referencia, nunca cambia el tipo o valor del objeto que hace referencia.In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

Conversiones unboxingUnboxing conversions

Una conversión unboxing permite un tipo de referencia para convertirse explícitamente a un value_type.An unboxing conversion permits a reference type to be explicitly converted to a value_type. Existe una conversión unboxing de los tipos object, dynamic y System.ValueType a cualquier non_nullable_value_typey desde cualquier interface_type a cualquier non_ nullable_value_type que implementa el interface_type.An unboxing conversion exists from the types object, dynamic and System.ValueType to any non_nullable_value_type, and from any interface_type to any non_nullable_value_type that implements the interface_type. Escriba además System.Enum puede aplicar la conversión unboxing a cualquier enum_type.Furthermore type System.Enum can be unboxed to any enum_type.

Existe una conversión unboxing de un tipo de referencia a un nullable_type si existe una conversión unboxing del tipo de referencia subyacente non_nullable_value_type de la nullable_type.An unboxing conversion exists from a reference type to a nullable_type if an unboxing conversion exists from the reference type to the underlying non_nullable_value_type of the nullable_type.

Un tipo de valor S tiene una conversión unboxing de un tipo de interfaz I si tiene una conversión unboxing de un tipo de interfaz I0 y I0 tiene una conversión de identidad a I.A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface type I0 and I0 has an identity conversion to I.

Un tipo de valor S tiene una conversión unboxing de un tipo de interfaz I si tiene una conversión unboxing de un tipo de interfaz o delegado I0 y I0 es convertible de varianza a I o Ies convertible de varianza a I0 (conversión de varianza).A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface or delegate type I0 and either I0 is variance-convertible to I or I is variance-convertible to I0 (Variance conversion).

Una operación de conversión unboxing consiste en comprobar primero que la instancia de objeto es un valor con conversión boxing de la dada value_typey, a continuación, copia el valor fuera de la instancia.An unboxing operation consists of first checking that the object instance is a boxed value of the given value_type, and then copying the value out of the instance. Conversión unboxing a una referencia nula a un nullable_type genera el valor null de la nullable_type.Unboxing a null reference to a nullable_type produces the null value of the nullable_type. Un struct puede aplicar la conversión unboxing del tipo System.ValueType, ya que es una clase base para todas las estructuras (herencia).A struct can be unboxed from the type System.ValueType, since that is a base class for all structs (Inheritance).

Se describe más detalladamente en las conversiones unboxing Conversiones Unboxing.Unboxing conversions are described further in Unboxing conversions.

Conversiones explícitas de dinámicasExplicit dynamic conversions

Existe una conversión explícita de dinámica de una expresión de tipo dynamic a cualquier tipo T.An explicit dynamic conversion exists from an expression of type dynamic to any type T. La conversión se enlaza dinámicamente (enlace dinámico), lo que significa que se buscará una conversión explícita en tiempo de ejecución desde el tipo de tiempo de ejecución de la expresión T.The conversion is dynamically bound (Dynamic binding), which means that an explicit conversion will be sought at run-time from the run-time type of the expression to T. Si no se encuentra ninguna conversión, se produce una excepción en tiempo de ejecución.If no conversion is found, a run-time exception is thrown.

Si el enlace dinámico de la conversión no es el deseado, la expresión se puede convertir en primer lugar a objecty, a continuación, al tipo deseado.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Supongamos que se define la clase siguiente:Assume the following class is defined:

class C
{
    int i;

    public C(int i) { this.i = i; }

    public static explicit operator C(string s) 
    {
        return new C(int.Parse(s));
    }
}

El ejemplo siguiente muestra las conversiones explícitas de dinámicas:The following example illustrates explicit dynamic conversions:

object o  = "1";
dynamic d = "2";

var c1 = (C)o; // Compiles, but explicit reference conversion fails
var c2 = (C)d; // Compiles and user defined conversion succeeds

La conversión de mejor o a C se encuentra en tiempo de compilación para ser una conversión explícita de referencia.The best conversion of o to C is found at compile-time to be an explicit reference conversion. Esto se produce un error en tiempo de ejecución, porque "1" no es en realidad un C.This fails at run-time, because "1" is not in fact a C. La conversión de d a C sin embargo, como una conversión explícita dinámica, se suspende en tiempo de ejecución, donde un usuario definió la conversión del tipo de tiempo de ejecución de d -- string --a C se encuentra, y se realiza correctamente.The conversion of d to C however, as an explicit dynamic conversion, is suspended to run-time, where a user defined conversion from the run-time type of d -- string -- to C is found, and succeeds.

Conversiones explícitas que implica parámetros de tipoExplicit conversions involving type parameters

Existen las siguientes conversiones explícitas para un parámetro de tipo dado T:The following explicit conversions exist for a given type parameter T:

  • De la clase base eficaz C de T a T y desde cualquier clase base de C a T.From the effective base class C of T to T and from any base class of C to T. En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión unboxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. En caso contrario, la conversión se ejecuta como una conversión de referencia explícita o conversión de identidad.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • De cualquier tipo de interfaz a T.From any interface type to T. En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión unboxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. En caso contrario, la conversión se ejecuta como una conversión de referencia explícita o conversión de identidad.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Desde T a cualquier interface_type I proporcionado no exista ya una conversión implícita de T a I.From T to any interface_type I provided there is not already an implicit conversion from T to I. En tiempo de ejecución, si T es un tipo de valor, la conversión se ejecuta como una conversión boxing seguida de una conversión explícita de referencia.At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. En caso contrario, la conversión se ejecuta como una conversión de referencia explícita o conversión de identidad.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Un parámetro de tipo U a T, que proporciona T depende U (restricciones de parámetro de tipo).From a type parameter U to T, provided T depends on U (Type parameter constraints). En tiempo de ejecución, si U es un tipo de valor, a continuación, T y U son necesariamente del mismo tipo y se realiza ninguna conversión.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. De lo contrario, si T es un tipo de valor, la conversión se ejecuta como una conversión unboxing.Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. En caso contrario, la conversión se ejecuta como una conversión de referencia explícita o conversión de identidad.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

Si T es sabe que un tipo de referencia, las conversiones anteriores están clasificadas como conversiones explícitas de referencia (conversiones explícitas de referencia).If T is known to be a reference type, the conversions above are all classified as explicit reference conversions (Explicit reference conversions). Si T no es sabe que un tipo de referencia, las conversiones anteriores se clasifican como conversiones unboxing (Conversiones Unboxing).If T is not known to be a reference type, the conversions above are classified as unboxing conversions (Unboxing conversions).

Las reglas anteriores no permiten que una conversión explícita directa de un parámetro de tipo sin restricciones a un tipo de interfaz, lo que podría resultar sorprendente.The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. La razón de esta regla es evitar la confusión y realizar la semántica de estas conversiones no cifradas.The reason for this rule is to prevent confusion and make the semantics of such conversions clear. Por ejemplo, consideremos la siguiente declaración:For example, consider the following declaration:

class X<T>
{
    public static long F(T t) {
        return (long)t;                // Error 
    }
}

Si la conversión explícita directa de t a int permiten, fácilmente uno podría esperar que X<int>.F(7) devolvería 7L.If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7) would return 7L. Sin embargo, no es así porque las conversiones numéricas estándares solo se consideran cuando se conocen los tipos numéricos en tiempo de enlace.However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. Para hacer que la semántica claras y en el ejemplo anterior se debe escribir:In order to make the semantics clear, the above example must instead be written:

class X<T>
{
    public static long F(T t) {
        return (long)(object)t;        // Ok, but will only work when T is long
    }
}

Este código se compilará, pero si se ejecuta X<int>.F(7) , a continuación, generaría una excepción en tiempo de ejecución, desde una conversión boxing int no se puede convertir directamente a un long.This code will now compile but executing X<int>.F(7) would then throw an exception at run-time, since a boxed int cannot be converted directly to a long.

Conversiones explícitas definidas por el usuarioUser-defined explicit conversions

Una conversión explícita definido por el usuario consta de una conversión explícita opcional estándar, seguida por la ejecución de un operador de conversión implícita o explícita definido por el usuario, seguido de otra conversión explícita opcional estándar.A user-defined explicit conversion consists of an optional standard explicit conversion, followed by execution of a user-defined implicit or explicit conversion operator, followed by another optional standard explicit conversion. Las reglas exactas para evaluar las conversiones explícitas definidas por el usuario se describen en de procesamiento de las conversiones explícitas definidas por el usuario.The exact rules for evaluating user-defined explicit conversions are described in Processing of user-defined explicit conversions.

Conversiones estándarStandard conversions

Las conversiones estándar son aquellas conversiones predefinidas que se pueden producir como parte de una conversión definida por el usuario.The standard conversions are those pre-defined conversions that can occur as part of a user-defined conversion.

Conversiones implícitas estándarStandard implicit conversions

Las siguientes conversiones implícitas se clasifican como conversiones implícitas estándar:The following implicit conversions are classified as standard implicit conversions:

Las conversiones implícitas estándares excluyen específicamente las conversiones implícitas definido por el usuario.The standard implicit conversions specifically exclude user-defined implicit conversions.

Conversiones explícitas estándarStandard explicit conversions

Las conversiones explícitas estándares son todas las conversiones implícitas estándares más el subconjunto de las conversiones explícitas para el que existe una conversión implícita estándar opuesta.The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. En otras palabras, si un estándar implícito no existe conversión de un tipo A a un tipo B, a continuación, existe una conversión explícita estándar de tipo A escriba B y del tipo B escriba A.In other words, if a standard implicit conversion exists from a type A to a type B, then a standard explicit conversion exists from type A to type B and from type B to type A.

Conversiones definidas por el usuarioUser-defined conversions

C# permite que las conversiones implícitas y explícitas predefinidas para ampliarse por conversiones definidas por el usuario.C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. Conversiones definidas por el usuario se introducen mediante la declaración de operadores de conversión (operadores de conversión) en tipos de clase y estructura.User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

Permite conversiones definidas por el usuarioPermitted user-defined conversions

C# permite que solo determinadas conversiones definidas por el usuario a declararse.C# permits only certain user-defined conversions to be declared. En concreto, no es posible volver a definir una conversión implícita o explícita ya existente.In particular, it is not possible to redefine an already existing implicit or explicit conversion.

Para un tipo de origen dado S y tipo de destino Tsi S o T son tipos que aceptan valores NULL, permiten S0 y T0 hacen referencia a sus tipos subyacentes, de lo contrario S0 y T0 son igual que S y T respectivamente.For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. Una clase o struct se puede declarar una conversión de un tipo de origen S a un tipo de destino T sólo si se cumplen todas las opciones siguientes:A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0 y T0 son tipos diferentes.S0 and T0 are different types.
  • Ya sea S0 o T0 es el tipo de clase o estructura en la que realiza la declaración del operador.Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • Ni S0 ni T0 es un interface_type.Neither S0 nor T0 is an interface_type.
  • Excluyendo las conversiones definidas por el usuario, no existe una conversión desde S a T o desde T a S.Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

Las restricciones que se aplican a las conversiones definidas por el usuario se explican con más detalle en operadores de conversión.The restrictions that apply to user-defined conversions are discussed further in Conversion operators.

Operadores de conversión de elevaciónLifted conversion operators

Dado un operador de conversión definido por el usuario que convierte de un tipo de valor distinto de NULL S a un tipo de valor distinto de NULL T, un eleva el operador de conversión existe que convierte de S? a T?.Given a user-defined conversion operator that converts from a non-nullable value type S to a non-nullable value type T, a lifted conversion operator exists that converts from S? to T?. Este operador de conversión de elevación realiza un desajuste de S? a S seguido de la conversión definida por el usuario de S a T seguida de un ajuste de T a T?, excepto en que un valor null con valores S? pasa directamente a un valor null con valores T?.This lifted conversion operator performs an unwrapping from S? to S followed by the user-defined conversion from S to T followed by a wrapping from T to T?, except that a null valued S? converts directly to a null valued T?.

Un operador de conversión de elevación tiene la misma clasificación implícita o explícita, como su operador de conversión definido por el usuario subyacente.A lifted conversion operator has the same implicit or explicit classification as its underlying user-defined conversion operator. El término "conversión definida por el usuario" se aplica al uso de ambos definido por el usuario y los operadores de conversión de elevación.The term "user-defined conversion" applies to the use of both user-defined and lifted conversion operators.

Evaluación de conversiones definidas por el usuarioEvaluation of user-defined conversions

Una conversión definida por el usuario convierte un valor de su tipo, denominado el tipo de origen, a otro tipo, denominado el tipo de destino.A user-defined conversion converts a value from its type, called the source type, to another type, called the target type. Evaluación de una conversión definida por el usuario se centra en encontrar el más específica operador de conversión definido por el usuario para los tipos de origen y de destino determinados.Evaluation of a user-defined conversion centers on finding the most specific user-defined conversion operator for the particular source and target types. Esta determinación se divide en varios pasos:This determination is broken into several steps:

  • Encontrar el conjunto de clases y structs desde el que se considerarán los operadores de conversión definido por el usuario.Finding the set of classes and structs from which user-defined conversion operators will be considered. Este conjunto está formado por el tipo de origen y sus clases base y el tipo de destino y sus clases base (con los supuestos implícitos que sólo las clases y structs pueden declarar los operadores definidos por el usuario, y que los tipos de clase no tienen ninguna clase base).This set consists of the source type and its base classes and the target type and its base classes (with the implicit assumptions that only classes and structs can declare user-defined operators, and that non-class types have no base classes). Para los fines de este paso, si el tipo de origen o destino es un nullable_type, su tipo subyacente se usa en su lugar.For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
  • Desde ese conjunto de tipos, determinar que definido por el usuario y eleva los operadores de conversión son aplicables.From that set of types, determining which user-defined and lifted conversion operators are applicable. Para que un operador de conversión sea aplicable, debe ser posible realizar una conversión estándar (conversiones estándar) del tipo de origen que el operando tipo del operador y debe ser posible realizar una conversión estándar desde el tipo de resultado del operador para el tipo de destino.For a conversion operator to be applicable, it must be possible to perform a standard conversion (Standard conversions) from the source type to the operand type of the operator, and it must be possible to perform a standard conversion from the result type of the operator to the target type.
  • Desde el conjunto de operadores definidos por el usuario aplicables, determinar qué operador es la más específica sin ambigüedades.From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. En términos generales, el operador más específico es el operador cuyo tipo de operando es "más cercana" al tipo de origen y cuyo tipo de resultado es "más cercana" al tipo de destino.In general terms, the most specific operator is the operator whose operand type is "closest" to the source type and whose result type is "closest" to the target type. Operadores de conversión de elevación se prefieren los operadores de conversión definido por el usuario.User-defined conversion operators are preferred over lifted conversion operators. Las reglas exactas para establecer el operador de conversión definido por el usuario más específico se definen en las secciones siguientes.The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

Una vez que se ha identificado un operador de conversión definido por el usuario más específico, la ejecución real de la conversión definida por el usuario implica hasta tres pasos:Once a most specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • En primer lugar, si es necesario, realizar una conversión estándar del tipo de origen para el tipo de operando del operador de conversión definido por el usuario o la elevación.First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
  • A continuación, invocar el operador de conversión definido por el usuario o la elevación para llevar a cabo la conversión.Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • Por último, si es necesario, realizar una conversión estándar desde el tipo de resultado del operador de conversión definido por el usuario o la elevación para el tipo de destino.Finally, if required, performing a standard conversion from the result type of the user-defined or lifted conversion operator to the target type.

Evaluación de una conversión definida por el usuario nunca implica a más de un operador de conversión definido por el usuario o la elevación.Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. En otras palabras, una conversión de tipo S escriba T ejecutará nunca primero una conversión definida por el usuario de S a X y, a continuación, ejecutar una conversión definida por el usuario de X a T.In other words, a conversion from type S to type T will never first execute a user-defined conversion from S to X and then execute a user-defined conversion from X to T.

Las definiciones exactas de la evaluación de las conversiones implícitas o explícitas definidas por el usuario se proporcionan en las secciones siguientes.Exact definitions of evaluation of user-defined implicit or explicit conversions are given in the following sections. Las definiciones de hacer uso de los siguientes términos:The definitions make use of the following terms:

  • Si una conversión implícita estándar (conversiones implícitas estándar) existe desde un tipo A a un tipo By si no A ni B son interface_types, A se dice que abarcado por B, y B se dice que abarcan A.If a standard implicit conversion (Standard implicit conversions) exists from a type A to a type B, and if neither A nor B are interface_types, then A is said to be encompassed by B, and B is said to encompass A.
  • El tipo más incluyente en un conjunto de tipos es un tipo que abarca todos los demás tipos en el conjunto.The most encompassing type in a set of types is the one type that encompasses all other types in the set. Si ningún tipo único abarca a todos los demás tipos, el conjunto no tiene ningún tipo más completa.If no single type encompasses all other types, then the set has no most encompassing type. En términos más intuitivos, el tipo más incluyente es el tipo "más grande" en el conjunto, un tipo al que puede convertirse implícitamente cada uno de los otros tipos.In more intuitive terms, the most encompassing type is the "largest" type in the set—the one type to which each of the other types can be implicitly converted.
  • El un tipo más abarcado en un conjunto de tipos es un tipo que está incluido en todos los demás tipos en el conjunto.The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. Si no los tipos es abarcado por todos los demás tipos, el conjunto más no ha abarcado a tipo.If no single type is encompassed by all other types, then the set has no most encompassed type. En términos más intuitivos, el tipo más abarcado es el tipo "más pequeño" en el conjunto, un tipo que pueda convertirse implícitamente a cada uno de los otros tipos.In more intuitive terms, the most encompassed type is the "smallest" type in the set—the one type that can be implicitly converted to each of the other types.

Procesamiento de las conversiones implícitas definido por el usuarioProcessing of user-defined implicit conversions

Una conversión implícita del tipo definido por el usuario S escriba T se procesa como sigue:A user-defined implicit conversion from type S to type T is processed as follows:

  • Determinar los tipos S0 y T0.Determine the types S0 and T0. Si S o T son tipos que aceptan valores NULL, S0 y T0 son sus tipos subyacentes, de lo contrario, S0 y T0 son iguales a S y T respectivamente.If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • Busque el conjunto de tipos, D, desde qué conversión definida por el usuario se considerarán los operadores.Find the set of types, D, from which user-defined conversion operators will be considered. Este conjunto consta de S0 (si S0 es una clase o struct), las clases base de S0 (si S0 es una clase), y T0 (si T0 es una clase o struct).This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), and T0 (if T0 is a class or struct).
  • Busque el conjunto de operadores de conversión definido por el usuario y la elevación aplicables, U.Find the set of applicable user-defined and lifted conversion operators, U. Este conjunto consta de los operadores de conversión implícita de elevación y definido por el usuario declarados por las clases o structs en D que convertir de un tipo que abarca S a un tipo englobado por T.This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in D that convert from a type encompassing S to a type encompassed by T. Si U está vacía, la conversión es indefinida y se produce un error de tiempo de compilación.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Busca el tipo de origen más específico, SX, de los operadores de U:Find the most specific source type, SX, of the operators in U:
    • Si cualquiera de los operadores en U convertir de S, a continuación, SX es S.If any of the operators in U convert from S, then SX is S.
    • En caso contrario, SX es el tipo más abarcado en el conjunto combinado de tipos de origen de los operadores de U.Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. Si exactamente uno más abarcado no se encuentra el tipo, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Busca el tipo de destino más específico, TX, de los operadores de U:Find the most specific target type, TX, of the operators in U:
    • Si cualquiera de los operadores en U convertir en T, a continuación, TX es T.If any of the operators in U convert to T, then TX is T.
    • En caso contrario, TX es el tipo más completa en el conjunto combinado de tipos de destino de los operadores de U.Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. Si no se encuentra exactamente un tipo más incluyente, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Buscar el operador de conversión más específico:Find the most specific conversion operator:
    • Si U contiene exactamente un operador de conversión definido por el usuario que convierte de SX a TX, este es el operador de conversión más específico.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • De lo contrario, si U contiene exactamente un operador de conversión de elevación que convierte de SX a TX, este es el operador de conversión más específico.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • En caso contrario, la conversión es ambigua y se produce un error de tiempo de compilación.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Por último, aplique la conversión:Finally, apply the conversion:
    • Si S no SX, a continuación, una conversión implícita estándar de S a SX se lleva a cabo.If S is not SX, then a standard implicit conversion from S to SX is performed.
    • Se invoca el operador de conversión más específico para convertir de SX a TX.The most specific conversion operator is invoked to convert from SX to TX.
    • Si TX no T, a continuación, una conversión implícita estándar de TX a T se lleva a cabo.If TX is not T, then a standard implicit conversion from TX to T is performed.

Procesamiento de las conversiones explícitas definidas por el usuarioProcessing of user-defined explicit conversions

Una conversión explícita de tipo definido por el usuario S escriba T se procesa como sigue:A user-defined explicit conversion from type S to type T is processed as follows:

  • Determinar los tipos S0 y T0.Determine the types S0 and T0. Si S o T son tipos que aceptan valores NULL, S0 y T0 son sus tipos subyacentes, de lo contrario, S0 y T0 son iguales a S y T respectivamente.If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • Busque el conjunto de tipos, D, desde qué conversión definida por el usuario se considerarán los operadores.Find the set of types, D, from which user-defined conversion operators will be considered. Este conjunto consta de S0 (si S0 es una clase o struct), las clases base de S0 (si S0 es una clase), T0 (si T0 es una clase o struct) y las clases base de T0 (si T0es una clase).This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), T0 (if T0 is a class or struct), and the base classes of T0 (if T0 is a class).
  • Busque el conjunto de operadores de conversión definido por el usuario y la elevación aplicables, U.Find the set of applicable user-defined and lifted conversion operators, U. Este conjunto consta de definido por el usuario y elevación implícita o declaran de operadores de conversión explícitos por las clases o structs en D que convertir de un tipo que abarca o abarcado por S a un tipo que abarca o abarcado por T.This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in D that convert from a type encompassing or encompassed by S to a type encompassing or encompassed by T. Si U está vacía, la conversión es indefinida y se produce un error de tiempo de compilación.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Busca el tipo de origen más específico, SX, de los operadores de U:Find the most specific source type, SX, of the operators in U:
    • Si cualquiera de los operadores en U convertir de S, a continuación, SX es S.If any of the operators in U convert from S, then SX is S.
    • En caso contrario, si cualquiera de los operadores en U convertir de tipos que abarca S, a continuación, SX es el tipo más abarcado en el conjunto combinado de tipos de origen de estos operadores.Otherwise, if any of the operators in U convert from types that encompass S, then SX is the most encompassed type in the combined set of source types of those operators. Si no hay más abarcado se encuentra un tipo, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
    • En caso contrario, SX es el tipo más completa en el conjunto combinado de tipos de origen de los operadores de U.Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. Si no se encuentra exactamente un tipo más incluyente, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Busca el tipo de destino más específico, TX, de los operadores de U:Find the most specific target type, TX, of the operators in U:
    • Si cualquiera de los operadores en U convertir en T, a continuación, TX es T.If any of the operators in U convert to T, then TX is T.
    • En caso contrario, si cualquiera de los operadores en U convertir a tipos abarcados por T, a continuación, TX es el tipo más completa en el conjunto combinado de tipos de destino de los operadores.Otherwise, if any of the operators in U convert to types that are encompassed by T, then TX is the most encompassing type in the combined set of target types of those operators. Si no se encuentra exactamente un tipo más incluyente, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
    • En caso contrario, TX es el tipo más abarcado en el conjunto combinado de tipos de destino de los operadores de U.Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. Si no hay más abarcado se encuentra un tipo, a continuación, la conversión es ambigua y se produce un error de tiempo de compilación.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
  • Buscar el operador de conversión más específico:Find the most specific conversion operator:
    • Si U contiene exactamente un operador de conversión definido por el usuario que convierte de SX a TX, este es el operador de conversión más específico.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • De lo contrario, si U contiene exactamente un operador de conversión de elevación que convierte de SX a TX, este es el operador de conversión más específico.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • En caso contrario, la conversión es ambigua y se produce un error de tiempo de compilación.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Por último, aplique la conversión:Finally, apply the conversion:
    • Si S no SX, a continuación, una conversión explícita estándar de S a SX se lleva a cabo.If S is not SX, then a standard explicit conversion from S to SX is performed.
    • Se invoca el operador de conversión definido por el usuario más específico para convertir de SX a TX.The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • Si TX no T, a continuación, una conversión explícita estándar de TX a T se lleva a cabo.If TX is not T, then a standard explicit conversion from TX to T is performed.

Conversiones de función anónimaAnonymous function conversions

Un anonymous_method_expression o lambda_expression se clasifica como una función anónima (expresiones de función anónima).An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). La expresión no tiene un tipo, pero puede convertirse implícitamente a un tipo de árbol de expresión o delegado compatible.The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. En concreto, una función anónima F es compatible con un tipo de delegado D proporcionado:Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Si F contiene un anonymous_function_signature, a continuación, D y F tienen el mismo número de parámetros.If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Si F no contiene un anonymous_function_signature, a continuación, D puede tener cero o más parámetros de cualquier tipo, siempre y cuando ningún parámetro de D tiene la out modificador de parámetro.If F does not contain an anonymous_function_signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.
  • Si F tiene una lista de parámetros con tipo explícito, cada parámetro de D tiene el mismo tipo y modificadores como el parámetro correspondiente en F.If F has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in F.
  • Si F tiene una lista de parámetros con tipo implícito, D no tiene ningún ref o out parámetros.If F has an implicitly typed parameter list, D has no ref or out parameters.
  • Si el cuerpo de F es una expresión y D tiene un void tipo de valor devuelto o F es asincrónico y D tiene el tipo de valor devuelto Task, entonces, cuando cada parámetro de F se le asigna el tipo de la el parámetro correspondiente en D, el cuerpo de F es una expresión válida (wrt expresiones) que se permitirían como un statement_expression (Las instrucciones de expresión).If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that would be permitted as a statement_expression (Expression statements).
  • Si el cuerpo de F es un bloque de instrucciones y D tiene un void tipo de valor devuelto o F es asincrónico y D tiene el tipo de valor devuelto Task, entonces, cuando cada parámetro de F se le asigna el tipo de el parámetro correspondiente en D, el cuerpo de F es un bloque de instrucciones válido (wrt bloques) no return instrucción especifica una expresión.If the body of F is a statement block, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) in which no return statement specifies an expression.
  • Si el cuerpo de F es una expresión, y cualquier F es que no es asincrónico y D tiene un tipo de valor devuelto distinto de void T, o F es asincrónico y D tiene un tipo de valor devuelto Task<T>, entonces, cuando cada parámetro de F tiene el tipo del parámetro correspondiente en D, el cuerpo de F es una expresión válida (wrt Las expresiones) que es implícitamente convertible a T.If the body of F is an expression, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that is implicitly convertible to T.
  • Si el cuerpo de F es un bloque de instrucciones, y cualquier F es que no es asincrónico y D tiene un tipo de valor devuelto distinto de void T, o F es asincrónico y D tiene un tipo de valor devuelto Task<T>, entonces, cuando cada parámetro de F tiene el tipo del parámetro correspondiente en D, el cuerpo de F es un bloque de instrucciones válido (wrt bloques ) con un punto de conexión que no sea accesible en el que cada return instrucción especifica una expresión que es implícitamente convertible a T.If the body of F is a statement block, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to T.

Para mayor brevedad, esta sección usa la forma abreviada para los tipos de tareas Task y Task<T> (funciones asincrónicas).For the purpose of brevity, this section uses the short form for the task types Task and Task<T> (Async functions).

Una expresión lambda F es compatible con un tipo de árbol de expresión Expression<D> si F es compatible con el tipo de delegado D.A lambda expression F is compatible with an expression tree type Expression<D> if F is compatible with the delegate type D. Tenga en cuenta que esto no es aplicable a los métodos anónimos, solo las expresiones lambda.Note that this does not apply to anonymous methods, only lambda expressions.

Algunas expresiones lambda no se puede convertir a tipos de árbol de expresión: Aunque la conversión existe, se produce un error en tiempo de compilación.Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. Este es el caso si la expresión lambda:This is the case if the lambda expression:

  • Tiene un bloque cuerpoHas a block body
  • Contiene los operadores de asignación simple o compuestaContains simple or compound assignment operators
  • Contiene una expresión enlazada dinámicamenteContains a dynamically bound expression
  • Es la asincroníaIs async

Los ejemplos siguientes usan un tipo de delegado genérico Func<A,R> que representa una función que toma un argumento de tipo A y devuelve un valor de tipo R:The examples that follow use a generic delegate type Func<A,R> which represents a function that takes an argument of type A and returns a value of type R:

delegate R Func<A,R>(A arg);

En las asignacionesIn the assignments

Func<int,int> f1 = x => x + 1;                 // Ok

Func<int,double> f2 = x => x + 1;              // Ok

Func<double,int> f3 = x => x + 1;              // Error

Func<int, Task<int>> f4 = async x => x + 1;    // Ok

los tipos de parámetro y valor devuelto de cada función anónima se determinan a partir del tipo de la variable al que se asigna la función anónima.the parameter and return types of each anonymous function are determined from the type of the variable to which the anonymous function is assigned.

La primera asignación convierte correctamente la función anónima en el tipo de delegado Func<int,int> porque, cuando x tiene tipo int, x+1 es una expresión válida que sea implícitamente convertible al tipo int.The first assignment successfully converts the anonymous function to the delegate type Func<int,int> because, when x is given type int, x+1 is a valid expression that is implicitly convertible to type int.

Del mismo modo, la segunda asignación convierte correctamente la función anónima en el tipo de delegado Func<int,double> porque el resultado de x+1 (de tipo int) es implícitamente convertible al tipo double.Likewise, the second assignment successfully converts the anonymous function to the delegate type Func<int,double> because the result of x+1 (of type int) is implicitly convertible to type double.

Sin embargo, la asignación de terceros es un error en tiempo de compilación porque, cuando x tiene tipo double, el resultado de x+1 (de tipo double) no es implícitamente convertible al tipo int.However, the third assignment is a compile-time error because, when x is given type double, the result of x+1 (of type double) is not implicitly convertible to type int.

El cuarta asignación convierte correctamente la función anónima asincrónico para el tipo de delegado Func<int, Task<int>> porque el resultado de x+1 (de tipo int) es implícitamente convertible al tipo de resultado int del tipo de tarea Task<int>.The fourth assignment successfully converts the anonymous async function to the delegate type Func<int, Task<int>> because the result of x+1 (of type int) is implicitly convertible to the result type int of the task type Task<int>.

Funciones anónimas pueden influir en la resolución de sobrecarga y participar en la inferencia de tipos.Anonymous functions may influence overload resolution, and participate in type inference. Consulte miembros de función para obtener más detalles.See Function members for further details.

Evaluación de función anónima conversiones a tipos de delegadoEvaluation of anonymous function conversions to delegate types

Conversión de una función anónima para un tipo de delegado, genera una instancia de delegado que hace referencia a la función anónima y el conjunto de variables externas capturadas que están activos en el momento de la evaluación (posiblemente vacío).Conversion of an anonymous function to a delegate type produces a delegate instance which references the anonymous function and the (possibly empty) set of captured outer variables that are active at the time of the evaluation. Cuando se invoca el delegado, se ejecuta el cuerpo de la función anónima.When the delegate is invoked, the body of the anonymous function is executed. Se ejecuta el código en el cuerpo con el conjunto de variables externas capturadas al que hace referencia el delegado.The code in the body is executed using the set of captured outer variables referenced by the delegate.

La lista de invocaciones de un delegado generada a partir de una función anónima contiene una sola entrada.The invocation list of a delegate produced from an anonymous function contains a single entry. El objeto de destino exacto y el método de destino del delegado se especifican.The exact target object and target method of the delegate are unspecified. En concreto, no se especifica si el objeto de destino del delegado es null, el this valor del miembro de función envolvente o algún otro objeto.In particular, it is unspecified whether the target object of the delegate is null, the this value of the enclosing function member, or some other object.

Las conversiones de funciones anónimas semánticamente idénticas con el mismo conjunto (posiblemente vacía) de instancias de variables externas capturadas en los mismos tipos de delegado se permiten (aunque no es necesario) para devolver la misma instancia de delegado.Conversions of semantically identical anonymous functions with the same (possibly empty) set of captured outer variable instances to the same delegate types are permitted (but not required) to return the same delegate instance. El término semánticamente idéntico se usa aquí para indicar que la ejecución de las funciones anónimas, en todos los casos, generará el mismo efecto que tiene los mismos argumentos.The term semantically identical is used here to mean that execution of the anonymous functions will, in all cases, produce the same effects given the same arguments. Esta regla permite que el código como el siguiente que se optimizarán.This rule permits code such as the following to be optimized.

delegate double Function(double x);

class Test
{
    static double[] Apply(double[] a, Function f) {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }

    static void F(double[] a, double[] b) {
        a = Apply(a, (double x) => Math.Sin(x));
        b = Apply(b, (double y) => Math.Sin(y));
        ...
    }
}

Puesto que los dos delegados de función anónima tienen igual (vacío) conjunto de variables externas capturadas y puesto que las funciones anónimas son semánticamente idénticas, el compilador puede tener delegados que hacen referencia al mismo método de destino.Since the two anonymous function delegates have the same (empty) set of captured outer variables, and since the anonymous functions are semantically identical, the compiler is permitted to have the delegates refer to the same target method. De hecho, el compilador puede devolver la misma instancia de delegado de ambas expresiones de función anónima.Indeed, the compiler is permitted to return the very same delegate instance from both anonymous function expressions.

Evaluación de función anónima conversiones a tipos de árbol de expresiónEvaluation of anonymous function conversions to expression tree types

Conversión de una función anónima en un tipo de árbol de expresión genera un árbol de expresión (tipos de árbol de expresión).Conversion of an anonymous function to an expression tree type produces an expression tree (Expression tree types). Más concretamente, la evaluación de la conversión de función anónima conduce a la construcción de una estructura de objeto que representa la estructura de la propia función anónima.More precisely, evaluation of the anonymous function conversion leads to the construction of an object structure that represents the structure of the anonymous function itself. La estructura de árbol de expresión, así como el proceso exacto para crearlo, precisa son implementación definida.The precise structure of the expression tree, as well as the exact process for creating it, are implementation defined.

Ejemplo de implementaciónImplementation example

Esta sección describe una posible implementación de las conversiones de función anónima en cuanto a otras construcciones de C#.This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. La implementación que se describen aquí se basa en los mismos principios utilizados por el compilador de C# de Microsoft, pero no es una implementación obligatoria, ni es el único posible.The implementation described here is based on the same principles used by the Microsoft C# compiler, but it is by no means a mandated implementation, nor is it the only one possible. Mencionan brevemente conversiones en árboles de expresión, como su semántica exacta está fuera del ámbito de esta especificación.It only briefly mentions conversions to expression trees, as their exact semantics are outside the scope of this specification.

El resto de esta sección proporciona varios ejemplos de código que contiene las funciones anónimas con diferentes características.The remainder of this section gives several examples of code that contains anonymous functions with different characteristics. Para cada ejemplo, se proporciona una traducción correspondiente al código que usa solo otras construcciones de C#.For each example, a corresponding translation to code that uses only other C# constructs is provided. En los ejemplos, el identificador D supone representan el siguiente tipo de delegado:In the examples, the identifier D is assumed by represent the following delegate type:

public delegate void D();

La forma más sencilla de una función anónima es uno que no captura variables externas:The simplest form of an anonymous function is one that captures no outer variables:

class Test
{
    static void F() {
        D d = () => { Console.WriteLine("test"); };
    }
}

Esto se puede traducir a una instancia de delegado que hace referencia a un método estático generado por el compilador en el que se coloca el código de la función anónima:This can be translated to a delegate instantiation that references a compiler generated static method in which the code of the anonymous function is placed:

class Test
{
    static void F() {
        D d = new D(__Method1);
    }

    static void __Method1() {
        Console.WriteLine("test");
    }
}

En el ejemplo siguiente, la función anónima, hace referencia a miembros de instancia de this:In the following example, the anonymous function references instance members of this:

class Test
{
    int x;

    void F() {
        D d = () => { Console.WriteLine(x); };
    }
}

Esto se puede traducir a un método de instancia generado por el compilador que contiene el código de la función anónima:This can be translated to a compiler generated instance method containing the code of the anonymous function:

class Test
{
    int x;

    void F() {
        D d = new D(__Method1);
    }

    void __Method1() {
        Console.WriteLine(x);
    }
}

En este ejemplo, la función anónima captura una variable local:In this example, the anonymous function captures a local variable:

class Test
{
    void F() {
        int y = 123;
        D d = () => { Console.WriteLine(y); };
    }
}

La duración de la variable local debe ser ampliada al menos la vigencia del delegado de función anónima.The lifetime of the local variable must now be extended to at least the lifetime of the anonymous function delegate. Esto puede lograrse mediante "uno" de la variable local en un campo de una clase generada por compilador.This can be achieved by "hoisting" the local variable into a field of a compiler generated class. Creación de instancias de la variable local (creación de instancias de las variables locales), a continuación, corresponde a la creación de una instancia de la clase generada por compilador y el acceso a la variable local corresponde al acceso a un campo en la instancia de la clase generada por compilador.Instantiation of the local variable (Instantiation of local variables) then corresponds to creating an instance of the compiler generated class, and accessing the local variable corresponds to accessing a field in the instance of the compiler generated class. Además, la función anónima se convierte en un método de instancia de la clase generada por compilador:Furthermore, the anonymous function becomes an instance method of the compiler generated class:

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.y = 123;
        D d = new D(__locals1.__Method1);
    }

    class __Locals1
    {
        public int y;

        public void __Method1() {
            Console.WriteLine(y);
        }
    }
}

Por último, la siguiente anónima función capturas this , así como dos variables locales con diferentes períodos de duración:Finally, the following anonymous function captures this as well as two local variables with different lifetimes:

class Test
{
    int x;

    void F() {
        int y = 123;
        for (int i = 0; i < 10; i++) {
            int z = i * 2;
            D d = () => { Console.WriteLine(x + y + z); };
        }
    }
}

En este caso, se crea una clase generada por compilador para cada instrucción bloque en que se capturan las variables locales que las variables locales en los distintos bloques pueden tengan duraciones independientes.Here, a compiler generated class is created for each statement block in which locals are captured such that the locals in the different blocks can have independent lifetimes. Una instancia de __Locals2, la clase generada por compilador para el bloque de instrucciones internas, contiene la variable local z y un campo que hace referencia a una instancia de __Locals1.An instance of __Locals2, the compiler generated class for the inner statement block, contains the local variable z and a field that references an instance of __Locals1. Una instancia de __Locals1, la clase generada por compilador para el bloque de instrucción externa, contiene la variable local y y un campo que hace referencia a this del miembro de función envolvente.An instance of __Locals1, the compiler generated class for the outer statement block, contains the local variable y and a field that references this of the enclosing function member. Con estas estructuras de datos, es posible obtener acceso a todas capturar variables externas a través de una instancia de __Local2, y el código de la función anónima, por tanto, se puede implementar como un método de instancia de esa clase.With these data structures it is possible to reach all captured outer variables through an instance of __Local2, and the code of the anonymous function can thus be implemented as an instance method of that class.

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.__this = this;
        __locals1.y = 123;
        for (int i = 0; i < 10; i++) {
            __Locals2 __locals2 = new __Locals2();
            __locals2.__locals1 = __locals1;
            __locals2.z = i * 2;
            D d = new D(__locals2.__Method1);
        }
    }

    class __Locals1
    {
        public Test __this;
        public int y;
    }

    class __Locals2
    {
        public __Locals1 __locals1;
        public int z;

        public void __Method1() {
            Console.WriteLine(__locals1.__this.x + __locals1.y + z);
        }
    }
}

También puede utilizar la misma técnica que se aplica aquí para capturar las variables locales al convertir las funciones anónimas en árboles de expresión: Referencias a los objetos generados por el compilador pueden almacenarse en el árbol de expresión y el acceso a las variables locales se puede representar como campo tiene acceso a estos objetos.The same technique applied here to capture local variables can also be used when converting anonymous functions to expression trees: References to the compiler generated objects can be stored in the expression tree, and access to the local variables can be represented as field accesses on these objects. La ventaja de este enfoque es que permite que las variables locales "elevación" para compartirse entre los delegados y árboles de expresión.The advantage of this approach is that it allows the "lifted" local variables to be shared between delegates and expression trees.

Conversiones de métodos de grupoMethod group conversions

Una conversión implícita (conversiones implícitas) existe desde un grupo de métodos (clasificaciones de expresiones) a un tipo delegado compatible.An implicit conversion (Implicit conversions) exists from a method group (Expression classifications) to a compatible delegate type. Dado un tipo de delegado D y una expresión E que se clasifica como un grupo de métodos, existe una conversión implícita de E a D si E contiene al menos un método que es aplicable en su forma normal () Miembro de función aplicable) a una lista de argumentos que se construye mediante el uso de los tipos de parámetros y modificadores de D, como se describe en la siguiente.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 (Applicable function member) to an argument list constructed by use of the parameter types and modifiers of D, as described in the following.

La aplicación en tiempo de compilación de una conversión de un grupo de métodos E a un tipo delegado D se describe en la siguiente.The compile-time application of a conversion from a method group E to a delegate type D is described in the following. Tenga en cuenta que la existencia de una conversión implícita de E a D no garantiza que la aplicación en tiempo de compilación de la conversión se realizará correctamente sin errores.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.

  • Un único método M se selecciona correspondiente a una invocación de método (las invocaciones de método) del formulario E(A), con las siguientes modificaciones:A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
    • La lista de argumentos A es una lista de expresiones, cada uno de ellos clasificadas como una variable y con el tipo y el modificador (ref o out) del parámetro correspondiente en el formal_parameter_list de D.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.
    • Los métodos de candidato considerados son solo aquellos métodos que son aplicables en su forma normal (miembro de función aplicable), no los aplicables únicamente en su forma expandida.The candidate methods considered are only those methods that are applicable in their normal form (Applicable function member), not those applicable only in their expanded form.
  • Si el algoritmo de las invocaciones de método produce un error, a continuación, se produce un error de tiempo de compilación.If the algorithm of Method invocations produces an error, then a compile-time error occurs. En caso contrario, el algoritmo genera un único método mejor M tener el mismo número de parámetros como D y la conversión se considera que existe.Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
  • El método seleccionado M deben ser compatibles (compatibilidad de delegado) con el tipo de delegado D, o en caso contrario, se produce un error en tiempo de compilación.The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
  • Si el método seleccionado M es un método de instancia, la expresión de instancia asociada E determina el objeto de destino del delegado.If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
  • Si el método seleccionado M es un método de extensión que se indica mediante un acceso de miembro en una expresión de instancia, esa expresión de instancia determina el objeto de destino del delegado.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.
  • El resultado de la conversión es un valor de tipo D, es decir, un delegado recién creado que hace referencia al objeto de método y el destino seleccionado.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.
  • Tenga en cuenta que este proceso puede dar lugar a la creación de un delegado a un método de extensión, si el algoritmo de las invocaciones de método no puede encontrar un método de instancia, pero se realiza correctamente en el procesamiento de la invocación de E(A) como una extensión invocación de método (las invocaciones de método de extensión).Note that this process can lead to the creation of a delegate to an extension method, if the algorithm of Method invocations fails to find an instance method but succeeds in processing the invocation of E(A) as an extension method invocation (Extension method invocations). Un delegado creado, por tanto, captura el método de extensión, así como su primer argumento.A delegate thus created captures the extension method as well as its first argument.

El ejemplo siguiente muestra las conversiones de grupo de métodos: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

    }
}

La asignación a d1 convierte implícitamente el grupo de métodos F en un valor de tipo D1.The assignment to d1 implicitly converts the method group F to a value of type D1.

La asignación a d2 muestra cómo es posible crear un delegado a un método que tiene tipos de parámetro menos derivados (contravariante) y una más derivado a tipo de valor devuelto (covariante).The assignment to d2 shows how it is possible to create a delegate to a method that has less derived (contravariant) parameter types and a more derived (covariant) return type.

La asignación a d3 muestra cómo no existe ninguna conversión si el método no es aplicable.The assignment to d3 shows how no conversion exists if the method is not applicable.

La asignación a d4 se muestra cómo el método debe ser aplicable en su forma normal.The assignment to d4 shows how the method must be applicable in its normal form.

La asignación a d5 se muestra cómo se permiten los tipos de parámetro y valor devuelto del método y delegado difieran solo para los tipos de referencia.The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

Al igual que con todas las otras conversiones implícitas y explícitas, el operador de conversión puede usarse para realizar explícitamente la conversión de grupos de un método.As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. Por lo tanto, el ejemploThus, the example

object obj = new EventHandler(myDialog.OkClick);

en su lugar se podría escribircould instead be written

object obj = (EventHandler)myDialog.OkClick;

Grupos de métodos pueden influir en la resolución de sobrecarga y participar en la inferencia de tipos.Method groups may influence overload resolution, and participate in type inference. Consulte miembros de función para obtener más detalles.See Function members for further details.

La evaluación de tiempo de ejecución de la conversión de grupos de un método continúa como sigue:The run-time evaluation of a method group conversion proceeds as follows:

  • Si el método seleccionado en tiempo de compilación es un método de instancia, o es un método de extensión que se obtiene acceso como un método de instancia, el objeto de destino del delegado se determina a partir de la expresión de instancia asociada E: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:
    • Se evalúa la expresión de instancia.The instance expression is evaluated. Si esta evaluación, produce una excepción, no se ejecuta ningún paso adicional.If this evaluation causes an exception, no further steps are executed.
    • Si la expresión de instancia es de un reference_type, el valor calculado por la expresión de instancia se convierte en el objeto de destino.If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. Si el método seleccionado es un método de instancia y el objeto de destino es null, un System.NullReferenceException se inicia y no se ejecuta ningún paso adicional.If the selected method is an instance method and the target object is null, a System.NullReferenceException is thrown and no further steps are executed.
    • Si la expresión de instancia es de un value_type, una operación de conversión boxing (conversiones Boxing) se realiza para convertir el valor a un objeto, y este objeto se convierte en el objeto de destino.If the instance expression is of a value_type, a boxing operation (Boxing conversions) is performed to convert the value to an object, and this object becomes the target object.
  • En caso contrario, el método seleccionado es parte de una llamada al método estático y el objeto de destino del delegado es null.Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
  • Una nueva instancia del tipo de delegado D está asignada.A new instance of the delegate type D is allocated. Si no hay suficiente memoria disponible para asignar la nueva instancia, un System.OutOfMemoryException se inicia y no se ejecuta ningún paso adicional.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • La nueva instancia de delegado se inicializa con una referencia al método que se determinó en tiempo de compilación y una referencia al objeto de destino calculado anteriormente.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.