ConversõesConversions

Uma conversão _ * permite que uma expressão seja tratada como sendo de um tipo específico.A *conversion _ enables an expression to be treated as being of a particular type. Uma conversão pode fazer com que uma expressão de um determinado tipo seja tratada como tendo um tipo diferente, ou pode causar uma expressão sem um tipo para obter um 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. As conversões podem ser implícitas ou _ Explicit *, e isso determina se uma conversão explícita é necessária.Conversions can be implicit or _*explicit**, and this determines whether an explicit cast is required. Por exemplo, a conversão de tipo int para tipo long é implícita, portanto, as expressões do tipo int podem ser tratadas implicitamente 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. A conversão oposta, de tipo long para tipo int , é explícita e, portanto, uma conversão explícita é necessária.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

Algumas conversões são definidas pelo idioma.Some conversions are defined by the language. Os programas também podem definir suas próprias conversões (conversões definidas pelo usuário).Programs may also define their own conversions (User-defined conversions).

Conversões implícitasImplicit conversions

As conversões a seguir são classificadas como conversões implícitas:The following conversions are classified as implicit conversions:

  • Conversões de identidadeIdentity conversions
  • Conversões numéricas implícitasImplicit numeric conversions
  • Conversões implícitas de enumeraçãoImplicit enumeration conversions
  • Conversões de cadeia de caracteres interpoladas implícitasImplicit interpolated string conversions
  • Conversões anuláveis implícitasImplicit nullable conversions
  • Conversões literais nulasNull literal conversions
  • Conversões de referência implícitasImplicit reference conversions
  • Conversões de BoxingBoxing conversions
  • Conversões dinâmicas implícitasImplicit dynamic conversions
  • Conversões de expressão de constante implícitaImplicit constant expression conversions
  • Conversões implícitas definidas pelo usuárioUser-defined implicit conversions
  • Conversões de função anônimaAnonymous function conversions
  • Conversões de grupo de métodosMethod group conversions

Conversões implícitas podem ocorrer em várias situações, incluindo invocações de membro de função (verificação de tempo de compilação da resolução dinâmica de sobrecarga), expressões de conversão (expressões de conversão) e atribuições (operadores de atribuição).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).

As conversões implícitas predefinidas sempre são bem sucedidos e nunca causam a geração de exceções.The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. Conversões implícitas definidas pelo usuário corretamente criadas também devem apresentar essas características.Properly designed user-defined implicit conversions should exhibit these characteristics as well.

Para fins de conversão, os tipos object e dynamic são considerados equivalentes.For the purposes of conversion, the types object and dynamic are considered equivalent.

No entanto, conversões dinâmicas (conversõesdinâmicas implícitas e conversões dinâmicas explícitas) se aplicam somente a expressões do tipo dynamic (o tipo dinâmico).However, dynamic conversions (Implicit dynamic conversions and Explicit dynamic conversions) apply only to expressions of type dynamic (The dynamic type).

Conversão de identidadeIdentity conversion

Uma conversão de identidade converte de qualquer tipo para o mesmo tipo.An identity conversion converts from any type to the same type. Essa conversão existe de modo que uma entidade que já tenha um tipo necessário seja considerada para ser conversível para esse tipo.This conversion exists such that an entity that already has a required type can be said to be convertible to that type.

  • Como object e dynamic são considerados equivalentes, há uma conversão de identidade entre object e e dynamic entre os tipos construídos que são iguais ao substituir todas as ocorrências de dynamic por 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.

Conversões numéricas implícitasImplicit numeric conversions

As conversões numéricas implícitas são:The implicit numeric conversions are:

  • De sbyte para short , int , long , float , double ou decimal .From sbyte to short, int, long, float, double, or decimal.
  • De byte para short , ushort ,,,,, int uint long ulong float , double ou decimal .From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • De short para int , long , float , double ou decimal .From short to int, long, float, double, or decimal.
  • De ushort para int ,,,,, uint long ulong float double ou decimal .From ushort to int, uint, long, ulong, float, double, or decimal.
  • Do int para long , float , double ou decimal .From int to long, float, double, or decimal.
  • De uint para long , ulong , float , double ou decimal .From uint to long, ulong, float, double, or decimal.
  • Do long para float , double ou decimal .From long to float, double, or decimal.
  • Do ulong para float , double ou decimal .From ulong to float, double, or decimal.
  • De char para ushort , int ,,,,, uint long ulong float double ou decimal .From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • De float a double.From float to double.

As conversões de int , uint , long ou ulong para float e de long ou ulong para double podem causar uma perda de precisão, mas nunca causarão uma perda de magnitude.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. As outras conversões numéricas implícitas nunca perdem nenhuma informação.The other implicit numeric conversions never lose any information.

Não há conversões implícitas para o char tipo, de modo que os valores dos outros tipos integrais não são convertidos automaticamente para o 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.

Conversões implícitas de enumeraçãoImplicit enumeration conversions

Uma conversão implícita de enumeração permite que o decimal_integer_literal 0 seja convertido em qualquer enum_type e em qualquer nullable_type cujo tipo subjacente seja um 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. No último caso, a conversão é avaliada convertendo para o enum_type subjacente e encapsulando o resultado (tipos anuláveis).In the latter case the conversion is evaluated by converting to the underlying enum_type and wrapping the result (Nullable types).

Conversões de cadeia de caracteres interpoladas implícitasImplicit interpolated string conversions

Uma conversão de cadeia de caracteres interpolada implícita permite que um interpolated_string_expression (cadeias de caracteres interpoladas) seja convertido em System.IFormattable ou 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).

Quando essa conversão é aplicada, um valor de cadeia de caracteres não é composto da cadeia de caracteres interpolada.When this conversion is applied a string value is not composed from the interpolated string. Em vez disso, uma instância do System.FormattableString é criada, conforme descrito em cadeias de caracteres interpoladas.Instead an instance of System.FormattableString is created, as further described in Interpolated strings.

Conversões anuláveis implícitasImplicit nullable conversions

Conversões implícitas predefinidas que operam em tipos de valores não anuláveis também podem ser usadas com formulários anuláveis desses tipos.Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. Para cada uma das conversões implícitas e numéricas predefinidas que convertem de um tipo de valor não anulável S para um tipo de valor não anulável T , existem as seguintes conversões anuláveis implícitas: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:

  • Uma conversão implícita de S? para T? .An implicit conversion from S? to T?.
  • Uma conversão implícita de S para T? .An implicit conversion from S to T?.

A avaliação de uma conversão anulável implícita com base em uma conversão subjacente do S para T prossegue da seguinte maneira:Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Se a conversão anulável for de S? para T? :If the nullable conversion is from S? to T?:

    • Se o valor de origem for NULL (a HasValue propriedade é false), o resultado será o valor nulo do tipo T? .If the source value is null (HasValue property is false), the result is the null value of type T?.
    • Caso contrário, a conversão é avaliada como um desempacotamento de S? para S , seguida pela conversão subjacente de S para T , seguida por um encapsulamento (tipos anuláveis) de T para 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?.
  • Se a conversão anulável for de S para T? , a conversão será avaliada como a conversão subjacente de S para T seguida de um encapsulamento de T para 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?.

Conversões literais nulasNull literal conversions

Uma conversão implícita existe do null literal para qualquer tipo anulável.An implicit conversion exists from the null literal to any nullable type. Essa conversão produz o valor nulo (tipos anuláveis) do tipo anulável especificado.This conversion produces the null value (Nullable types) of the given nullable type.

Conversões de referência implícitasImplicit reference conversions

As conversões de referência implícitas são:The implicit reference conversions are:

  • De qualquer reference_type para object e dynamic .From any reference_type to object and dynamic.
  • De qualquer class_type S a qualquer class_type T , fornecida S é derivada de T .From any class_type S to any class_type T, provided S is derived from T.
  • De qualquer class_type S a qualquer interface_type T , fornecida S implementa T .From any class_type S to any interface_type T, provided S implements T.
  • De qualquer interface_type S a qualquer interface_type T , fornecida S é derivada de T .From any interface_type S to any interface_type T, provided S is derived from T.
  • De um array_type S com um tipo de elemento SE para um array_type T com um tipo de elemento TE , desde que todas as seguintes opções sejam verdadeiras: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 e T difere somente no tipo de elemento.S and T differ only in element type. Em outras palavras, S e T têm o mesmo número de dimensões.In other words, S and T have the same number of dimensions.
    • Ambos SE e TE são reference_type s.Both SE and TE are reference_type s.
    • Existe uma conversão de referência implícita de SE para TE .An implicit reference conversion exists from SE to TE.
  • De qualquer array_type para System.Array o e as interfaces que ele implementa.From any array_type to System.Array and the interfaces it implements.
  • De um tipo de matriz unidimensional S[] para System.Collections.Generic.IList<T> o e suas interfaces base, desde que haja uma conversão implícita de identidade ou referência de S para 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.
  • De qualquer delegate_type para System.Delegate o e as interfaces que ele implementa.From any delegate_type to System.Delegate and the interfaces it implements.
  • Do literal nulo para qualquer reference_type.From the null literal to any reference_type.
  • De qualquer reference_type a uma reference_type T se ele tiver uma conversão implícita de identidade ou referência para uma reference_type T0 e T0 tiver uma conversão de identidade para 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.
  • De qualquer reference_type a uma interface ou tipo delegado T , se ele tiver uma conversão implícita de identidade ou referência para uma interface ou tipo delegado T0 e T0 for conversível (conversão de variância) para 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.
  • Conversões implícitas envolvendo parâmetros de tipo que são conhecidos como tipos de referência.Implicit conversions involving type parameters that are known to be reference types. Confira conversões implícitas envolvendo parâmetros de tipo para obter mais detalhes sobre conversões implícitas envolvendo parâmetros de tipo.See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

As conversões de referência implícitas são aquelas que são conversões entre reference_type s que podem ser comprovadas sempre com sucesso e, portanto, não exigem verificações em tempo de execução.The implicit reference conversions are those conversions between reference_type s that can be proven to always succeed, and therefore require no checks at run-time.

As conversões de referência, implícita ou explícita, nunca alteram a identidade referencial do objeto que está sendo convertido.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. Em outras palavras, embora uma conversão de referência possa alterar o tipo da referência, ela nunca altera o tipo ou o valor do objeto que está sendo referenciado.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.

Conversões de BoxingBoxing conversions

Uma conversão boxing permite que um value_type seja convertido implicitamente em um tipo de referência.A boxing conversion permits a value_type to be implicitly converted to a reference type. Existe uma conversão boxing de qualquer non_nullable_value_type para object e para dynamic System.ValueType e para qualquer interface_type implementada pelo 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. Além disso, um enum_type pode ser convertido para o tipo System.Enum .Furthermore an enum_type can be converted to the type System.Enum.

Uma conversão boxing existe de um nullable_type para um tipo de referência, se e somente se uma conversão boxing existir do non_nullable_value_type subjacente para o tipo de referência.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.

Um tipo de valor tem uma conversão boxing para um tipo de interface I se ele tiver uma conversão boxing em um tipo de interface I0 e I0 tiver uma conversão de identidade para 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.

Um tipo de valor tem uma conversão boxing para um tipo de interface I se ele tiver uma conversão boxing para uma interface ou tipo delegado I0 e I0 for de variância conversível (conversão de variância) para 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.

Boxing um valor de uma non_nullable_value_type consiste em alocar uma instância de objeto e copiar o valor de value_type nessa instância.Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. Uma struct pode ser encaixada no tipo System.ValueType , pois essa é uma classe base para todas as structs (herança).A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

Boxing um valor de uma nullable_type procede da seguinte maneira:Boxing a value of a nullable_type proceeds as follows:

  • Se o valor de origem for NULL (a HasValue propriedade é false), o resultado será uma referência nula do tipo de destino.If the source value is null (HasValue property is false), the result is a null reference of the target type.
  • Caso contrário, o resultado é uma referência a um encaixado T produzido por desencapsulamento e conversão de código-fonte do valor de origem.Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

As conversões Boxing são descritas em mais detalhes nas conversões Boxing.Boxing conversions are described further in Boxing conversions.

Conversões dinâmicas implícitasImplicit dynamic conversions

Existe uma conversão dinâmica implícita de uma expressão do tipo dynamic para qualquer tipo T .An implicit dynamic conversion exists from an expression of type dynamic to any type T. A conversão é vinculada dinamicamente (associação dinâmica), o que significa que uma conversão implícita será procurada em tempo de execução do tipo de tempo de execução da expressão para 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. Se nenhuma conversão for encontrada, uma exceção de tempo de execução será lançada.If no conversion is found, a run-time exception is thrown.

Observe que essa conversão implícita aparentemente viola o Conselho no início de conversões implícitas que uma conversão implícita nunca deve causar uma exceção.Note that this implicit conversion seemingly violates the advice in the beginning of Implicit conversions that an implicit conversion should never cause an exception. No entanto, ela não é a conversão em si, mas a localização da conversão que causa a exceção.However it is not the conversion itself, but the finding of the conversion that causes the exception. O risco de exceções em tempo de execução é inerente ao uso de associação dinâmica.The risk of run-time exceptions is inherent in the use of dynamic binding. Se a vinculação dinâmica da conversão não for desejada, a expressão poderá ser convertida primeiro para object e, em seguida, para o tipo desejado.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

O exemplo a seguir ilustra as conversões dinâmicas implícitas: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

As atribuições para s2 e i ambas empregam conversões dinâmicas implícitas, em que a Associação das operações é suspensa até o tempo de execução.The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. Em tempo de execução, as conversões implícitas são buscadas do tipo de tempo de execução de d -- string --para o tipo de destino.At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. Uma conversão é encontrada para string , mas não para int .A conversion is found to string but not to int.

Conversões de expressão de constante implícitaImplicit constant expression conversions

Uma conversão de expressão constante implícita permite as seguintes conversões:An implicit constant expression conversion permits the following conversions:

  • Um constant_expression (expressões constantes) do tipo int pode ser convertido em tipo sbyte , byte ,,, ou, short desde que ushort uint ulong o valor da constant_expression esteja dentro do intervalo do 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.
  • Uma constant_expression do tipo long pode ser convertida para o tipo ulong , desde que o valor da constant_expression não seja negativo.A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

Conversões implícitas envolvendo parâmetros de tipoImplicit conversions involving type parameters

Existem as seguintes conversões implícitas para um determinado parâmetro de tipo T :The following implicit conversions exist for a given type parameter T:

  • De T para sua classe base efetiva C , de T para qualquer classe base de C , e de T para qualquer interface implementada pelo 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. Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. Caso contrário, a conversão é executada como uma conversão de referência implícita ou conversão de identidade.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • De T para um tipo de interface I no T conjunto de interfaces efetivas e de T para qualquer interface base do I .From T to an interface type I in T's effective interface set and from T to any base interface of I. Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. Caso contrário, a conversão é executada como uma conversão de referência implícita ou conversão de identidade.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • De T para um parâmetro de tipo U , fornecido T depende de U (restrições de parâmetro detipo).From T to a type parameter U, provided T depends on U (Type parameter constraints). Em tempo de execução, se U for um tipo de valor, será, T U necessariamente, o mesmo tipo e nenhuma conversão será executada.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. Caso contrário, se T for um tipo de valor, a conversão será executada como uma conversão boxing.Otherwise, if T is a value type, the conversion is executed as a boxing conversion. Caso contrário, a conversão é executada como uma conversão de referência implícita ou conversão de identidade.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Do literal nulo para T , fornecido T é conhecido como um tipo de referência.From the null literal to T, provided T is known to be a reference type.
  • De T para um tipo de referência I se ele tiver uma conversão implícita para um tipo de referência S0 e S0 tiver uma conversão de identidade para 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. Em tempo de execução, a conversão é executada da mesma maneira que a conversão para S0 .At run-time the conversion is executed the same way as the conversion to S0.
  • De T para um tipo de interface I se ele tem uma conversão implícita para uma interface ou tipo delegado I0 e I0 é convertido em variância para I (conversão devariância).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). Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. Caso contrário, a conversão é executada como uma conversão de referência implícita ou conversão de identidade.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

Se T for conhecido como um tipo de referência (restrições de parâmetro de tipo), as conversões acima serão todas classificadas como conversões de referência implícita (conversões de referência implícitas).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). Se T não for conhecido como um tipo de referência, as conversões acima serão classificadas como conversões Boxing (conversões Boxing).If T is not known to be a reference type, the conversions above are classified as boxing conversions (Boxing conversions).

Conversões implícitas definidas pelo usuárioUser-defined implicit conversions

Uma conversão implícita definida pelo usuário consiste em uma conversão implícita padrão opcional, seguida pela execução de um operador de conversão implícita definido pelo usuário, seguido por outra conversão implícita padrão opcional.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. As regras exatas para avaliar conversões implícitas definidas pelo usuário são descritas em processamento de conversões implícitas definidas pelo usuário.The exact rules for evaluating user-defined implicit conversions are described in Processing of user-defined implicit conversions.

Conversões de função anônima e conversões de grupo de métodosAnonymous function conversions and method group conversions

Funções anônimas e grupos de métodos não têm tipos próprios, mas podem ser convertidos implicitamente em tipos delegados ou tipos de árvore de expressão.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. As conversões de função anônimas são descritas mais detalhadamente em conversões de função anônima e conversões de grupo de métodos em conversões de grupos de métodos.Anonymous function conversions are described in more detail in Anonymous function conversions and method group conversions in Method group conversions.

Conversões explícitasExplicit conversions

As conversões a seguir são classificadas como conversões explícitas:The following conversions are classified as explicit conversions:

  • Todas as conversões implícitas.All implicit conversions.
  • Conversões numéricas explícitas.Explicit numeric conversions.
  • Conversões de enumeração explícitas.Explicit enumeration conversions.
  • Conversões anuláveis explícitas.Explicit nullable conversions.
  • Conversões de referência explícita.Explicit reference conversions.
  • Conversões de interface explícitas.Explicit interface conversions.
  • Conversões de unboxing.Unboxing conversions.
  • Conversões dinâmicas explícitasExplicit dynamic conversions
  • Conversões explícitas definidas pelo usuário.User-defined explicit conversions.

Conversões explícitas podem ocorrer em expressões de conversão (expressões de conversão).Explicit conversions can occur in cast expressions (Cast expressions).

O conjunto de conversões explícitas inclui todas as conversões implícitas.The set of explicit conversions includes all implicit conversions. Isso significa que as expressões de conversão redundantes são permitidas.This means that redundant cast expressions are allowed.

As conversões explícitas que não são conversões implícitas são conversões que não podem ser comprovadas sempre com sucesso, conversões que são conhecidas por possivelmente perderem informações e conversões em domínios de tipos suficientemente diferentes para a notação explícita de mérito.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.

Conversões numéricas explícitasExplicit numeric conversions

As conversões numéricas explícitas são as conversões de um numeric_type para outro numeric_type para o qual uma conversão numérica implícita (conversões numéricas implícitas) ainda não 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:

  • De sbyte para byte , ushort , uint , ulong ou char .From sbyte to byte, ushort, uint, ulong, or char.
  • De byte para sbyte e char .From byte to sbyte and char.
  • De short para sbyte , byte , ushort , uint , ulong ou char .From short to sbyte, byte, ushort, uint, ulong, or char.
  • Do ushort para sbyte , byte , short ou char .From ushort to sbyte, byte, short, or char.
  • De int para sbyte ,,,,, byte short ushort uint ulong ou char .From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • De uint para sbyte , byte , short , ushort , int ou char .From uint to sbyte, byte, short, ushort, int, or char.
  • De long para sbyte , byte ,,,,, short ushort int uint ulong ou char .From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • De ulong para sbyte , byte ,,,,, short ushort int uint long ou char .From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • Do char para sbyte , byte ou short .From char to sbyte, byte, or short.
  • De float para sbyte , byte ,,,,, short ushort int uint long , ulong , char ou decimal .From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • De double para sbyte , byte ,,,,, short ushort int uint long , ulong , char , float ou decimal .From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • De decimal para sbyte , byte ,,,,, short ushort int uint long , ulong , char , float ou double .From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

Como as conversões explícitas incluem todas as conversões numéricas implícitas e explícitas, sempre é possível converter de qualquer numeric_type em qualquer outro numeric_type usando uma expressão de conversão (expressões de conversão).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).

As conversões numéricas explícitas possivelmente perdem informações ou possivelmente causam a geração de exceções.The explicit numeric conversions possibly lose information or possibly cause exceptions to be thrown. Uma conversão numérica explícita é processada da seguinte maneira:An explicit numeric conversion is processed as follows:

  • Para uma conversão de um tipo integral para outro tipo integral, o processamento depende do contexto de verificação de estouro (os operadores marcados e desmarcados) nos quais a conversão ocorre: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:
    • Em um checked contexto, a conversão terá sucesso se o valor do operando de origem estiver dentro do intervalo do tipo de destino, mas lançará um System.OverflowException se o valor do operando de origem estiver fora do intervalo do 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.
    • Em um unchecked contexto, a conversão sempre é bem sucedido e prossegue da seguinte maneira.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Se o tipo de origem for maior do que o tipo de destino, então o valor de origem será truncado descartando seus bits "extra" mais significativos.If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. O resultado é então tratado como um valor do tipo de destino.The result is then treated as a value of the destination type.
      • Se o tipo de origem for menor do que o tipo de destino, então o valor de origem será estendido por sinal ou por zero para que tenha o mesmo tamanho que o 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. A extensão por sinal será usada se o tipo de origem tiver sinal; a extensão por zero será usada se o tipo de origem não tiver sinal.Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. O resultado é então tratado como um valor do tipo de destino.The result is then treated as a value of the destination type.
      • Se o tipo de origem tiver o mesmo tamanho que o tipo de destino, então o valor de origem será tratado como um valor do 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 uma conversão de decimal para um tipo integral, o valor de origem é arredondado para zero para o valor integral mais próximo, e esse valor integral se torna o resultado da conversão.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. Se o valor integral resultante estiver fora do intervalo do tipo de destino, um System.OverflowException será lançado.If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • Para uma conversão de float ou double para um tipo integral, o processamento depende do contexto de verificação de estouro (os operadores marcados e desmarcados) nos quais a conversão ocorre: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:
    • Em um checked contexto, a conversão continua da seguinte maneira:In a checked context, the conversion proceeds as follows:
      • Se o valor do operando for NaN ou infinito, um System.OverflowException será gerado.If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
      • Caso contrário, o operando de origem será arredondado em direção a zero para o valor integral mais próximo.Otherwise, the source operand is rounded towards zero to the nearest integral value. Se esse valor integral estiver dentro do intervalo do tipo de destino, esse valor será o resultado da conversão.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • Caso contrário, uma System.OverflowException será gerada.Otherwise, a System.OverflowException is thrown.
    • Em um unchecked contexto, a conversão sempre é bem sucedido e prossegue da seguinte maneira.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Se o valor do operando for NaN ou infinito, o resultado da conversão será um valor não especificado do 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.
      • Caso contrário, o operando de origem será arredondado em direção a zero para o valor integral mais próximo.Otherwise, the source operand is rounded towards zero to the nearest integral value. Se esse valor integral estiver dentro do intervalo do tipo de destino, esse valor será o resultado da conversão.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • Caso contrário, o resultado da conversão é um valor não especificado do tipo de destino.Otherwise, the result of the conversion is an unspecified value of the destination type.
  • Para uma conversão de double para float , o double valor é arredondado para o valor mais próximo float .For a conversion from double to float, the double value is rounded to the nearest float value. Se o double valor for muito pequeno para representar como um float , o resultado se tornará positivo zero ou negativo zero.If the double value is too small to represent as a float, the result becomes positive zero or negative zero. Se o double valor for muito grande para representar como um float , o resultado se tornará infinito positivo ou infinito negativo.If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. Se o double valor for NaN, o resultado também será Nan.If the double value is NaN, the result is also NaN.
  • Para uma conversão de float ou double para decimal , o valor de origem é convertido em decimal representação e arredondado para o número mais próximo após a casa decimal 28, se necessário (o 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). Se o valor de origem for muito pequeno para representar como um decimal , o resultado se tornará zero.If the source value is too small to represent as a decimal, the result becomes zero. Se o valor de Source for NaN, Infinity ou muito grande para representar como um decimal , um System.OverflowException será lançado.If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • Para uma conversão de decimal para float ou double , o decimal valor é arredondado para o valor mais próximo double ou float .For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. Embora essa conversão possa perder a precisão, ela nunca faz com que uma exceção seja gerada.While this conversion may lose precision, it never causes an exception to be thrown.

Conversões de enumeração explícitasExplicit enumeration conversions

As conversões de enumeração explícitas são:The explicit enumeration conversions are:

  • De sbyte , byte , short , ushort , int , uint , long , ulong , char , float , double ou decimal para qualquer enum_type.From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
  • De qualquer enum_type para,,,,,,, sbyte byte short ushort int uint long ulong , char , float , double ou decimal .From any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
  • De qualquer enum_type a qualquer outro enum_type.From any enum_type to any other enum_type.

Uma conversão de enumeração explícita entre dois tipos é processada tratando qualquer enum_type participante como o tipo subjacente do enum_type e, em seguida, executando uma conversão numérica implícita ou explícita entre os 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 exemplo, dado um enum_type E com o e o tipo subjacente de int , uma conversão de E para byte é processada como uma conversão numérica explícita (conversões numéricas explícitas) de int para byte e uma conversão de byte para E é processada como uma conversão numérica implícita (conversões numéricas implícitas) de byte para 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.

Conversões anuláveis explícitasExplicit nullable conversions

As conversões anuláveis explícitas permitem conversões explícitas predefinidas que operam em tipos de valores não anuláveis para também serem usadas com formulários anuláveis desses tipos.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 uma das conversões explícitas predefinidas que convertem de um tipo de valor não anulável S para um tipo de valor não anulável T (conversão de identidade, conversões numéricas implícitas, conversões implícitas de enumeração, conversões numéricas explícitase conversões de enumeração explícitas), existem as seguintes conversões anuláveis: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:

  • Uma conversão explícita de S? para T? .An explicit conversion from S? to T?.
  • Uma conversão explícita de S para T? .An explicit conversion from S to T?.
  • Uma conversão explícita de S? para T .An explicit conversion from S? to T.

A avaliação de uma conversão anulável com base em uma conversão subjacente do S para T prossegue da seguinte maneira:Evaluation of a nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Se a conversão anulável for de S? para T? :If the nullable conversion is from S? to T?:
    • Se o valor de origem for NULL (a HasValue propriedade é false), o resultado será o valor nulo do tipo T? .If the source value is null (HasValue property is false), the result is the null value of type T?.
    • Caso contrário, a conversão é avaliada como um desempacotamento de S? para S , seguida pela conversão subjacente de S para T , seguida de um encapsulamento de T para 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?.
  • Se a conversão anulável for de S para T? , a conversão será avaliada como a conversão subjacente de S para T seguida de um encapsulamento de T para 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?.
  • Se a conversão anulável for de S? para T , a conversão será avaliada como um desempacotamento de S? para S seguido pela conversão subjacente de S para 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.

Observe que uma tentativa de desencapsular um valor anulável gerará uma exceção se o valor for null .Note that an attempt to unwrap a nullable value will throw an exception if the value is null.

Conversões de referência explícitasExplicit reference conversions

As conversões de referência explícitas são:The explicit reference conversions are:

  • De object e dynamic para qualquer outro reference_type.From object and dynamic to any other reference_type.
  • De qualquer class_type S a qualquer class_type T , fornecido S é uma classe base de T .From any class_type S to any class_type T, provided S is a base class of T.
  • De qualquer class_type S a qualquer interface_type T , fornecido S não é lacrado e fornecido não S implementa T .From any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
  • De qualquer interface_type S a qualquer class_type T , fornecida T não é uma implementação selada ou fornecida T S .From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • De qualquer interface_type S a qualquer interface_type T , fornecido S não é derivado de T .From any interface_type S to any interface_type T, provided S is not derived from T.
  • De um array_type S com um tipo de elemento SE para um array_type T com um tipo de elemento TE , desde que todas as seguintes opções sejam verdadeiras: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 e T difere somente no tipo de elemento.S and T differ only in element type. Em outras palavras, S e T têm o mesmo número de dimensões.In other words, S and T have the same number of dimensions.
    • Ambos SE e TE são reference_type s.Both SE and TE are reference_type s.
    • Existe uma conversão de referência explícita de SE para TE .An explicit reference conversion exists from SE to TE.
  • System.ArrayE as interfaces que ele implementa para qualquer array_type.From System.Array and the interfaces it implements to any array_type.
  • De um tipo de matriz unidimensional S[] para System.Collections.Generic.IList<T> o e suas interfaces base, desde que haja uma conversão de referência explícita de S para 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.
  • De System.Collections.Generic.IList<S> e suas interfaces base para um tipo de matriz unidimensional T[] , desde que haja uma conversão explícita de identidade ou referência de S para 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.
  • System.DelegateE as interfaces que ele implementa para qualquer delegate_type.From System.Delegate and the interfaces it implements to any delegate_type.
  • De um tipo de referência para um tipo de referência T se ele tiver uma conversão de referência explícita para um tipo de referência T0 e T0 tiver uma conversão de identidade 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.
  • De um tipo de referência para uma interface ou tipo delegado T se ele tiver uma conversão de referência explícita para um tipo de interface ou delegado T0 e T0 for conversível em variância T ou se T for convertido em variância para T0 (conversão devariância).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).
  • De D<S1...Sn> para D<T1...Tn> onde D<X1...Xn> é um tipo de delegado genérico, D<S1...Sn> não é compatível com or idêntico a D<T1...Tn> e para cada parâmetro Xi de tipo das D seguintes isenções: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:
    • Se Xi for invariável, Si será idêntico a Ti .If Xi is invariant, then Si is identical to Ti.
    • Se Xi for covariant, haverá uma identidade implícita ou explícita ou conversão de referência de Si para Ti .If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
    • Se Xi for contravariant, então Si será Ti idêntico ou ambos os tipos de referência.If Xi is contravariant, then Si and Ti are either identical or both reference types.
  • Conversões explícitas envolvendo parâmetros de tipo que são conhecidos como tipos de referência.Explicit conversions involving type parameters that are known to be reference types. Para obter mais detalhes sobre conversões explícitas envolvendo parâmetros de tipo, consulte conversões explícitas envolvendo parâmetros de tipo.For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

As conversões de referência explícitas são as conversões entre os tipos de referência que exigem verificações de tempo de execução para garantir que estejam corretos.The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

Para que uma conversão de referência explícita tenha sucesso em tempo de execução, o valor do operando de origem deve ser null , ou o tipo real do objeto referenciado pelo operando de origem deve ser um tipo que pode ser convertido para o tipo de destino por uma conversão de referência implícita (conversões de referência implícita) ou conversão boxing (conversões 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). Se uma conversão de referência explícita falhar, um System.InvalidCastException será lançado.If an explicit reference conversion fails, a System.InvalidCastException is thrown.

As conversões de referência, implícita ou explícita, nunca alteram a identidade referencial do objeto que está sendo convertido.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. Em outras palavras, embora uma conversão de referência possa alterar o tipo da referência, ela nunca altera o tipo ou o valor do objeto que está sendo referenciado.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.

Conversões de unboxingUnboxing conversions

Uma conversão sem Boxing permite que um tipo de referência seja explicitamente convertido em um value_type.An unboxing conversion permits a reference type to be explicitly converted to a value_type. Existe uma conversão de irboxing dos tipos object , dynamic e System.ValueType para qualquer non_nullable_value_type e de qualquer interface_type a qualquer non_nullable_value_type que implemente o 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. Além disso, o tipo System.Enum pode ser desemoldurado para qualquer enum_type.Furthermore type System.Enum can be unboxed to any enum_type.

Uma conversão unboxing existe de um tipo de referência para um nullable_type se existir uma conversão unboxing do tipo de referência para o non_nullable_value_type subjacente do 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.

Um tipo de valor S tem uma conversão unboxing de um tipo de interface I se ele tiver uma conversão unboxing de um tipo de interface I0 e I0 tiver uma conversão de identidade para 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.

Um tipo de valor S tem uma conversão unboxing de um tipo de interface I se ele tem uma conversão unboxing de uma interface ou um tipo delegado, I0 e I0 é convertido em variância ou pode ser I convertido em I variância I0 (conversão devariância).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).

Uma operação de unboxing consiste na primeira verificação de que a instância do objeto é um valor em caixa do determinado value_type e, em seguida, copiar o valor para fora da instância.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. Unboxing uma referência nula a um nullable_type produz o valor nulo do nullable_type.Unboxing a null reference to a nullable_type produces the null value of the nullable_type. Uma struct pode ser desemoldurada do tipo System.ValueType , pois essa é uma classe base para todas as structs (herança).A struct can be unboxed from the type System.ValueType, since that is a base class for all structs (Inheritance).

As conversões de unboxing são descritas em detalhes em conversões unboxing.Unboxing conversions are described further in Unboxing conversions.

Conversões dinâmicas explícitasExplicit dynamic conversions

Existe uma conversão dinâmica explícita de uma expressão do tipo dynamic para qualquer tipo T .An explicit dynamic conversion exists from an expression of type dynamic to any type T. A conversão é vinculada dinamicamente (associação dinâmica), o que significa que uma conversão explícita será procurada em tempo de execução do tipo de tempo de execução da expressão para 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. Se nenhuma conversão for encontrada, uma exceção de tempo de execução será lançada.If no conversion is found, a run-time exception is thrown.

Se a vinculação dinâmica da conversão não for desejada, a expressão poderá ser convertida primeiro para object e, em seguida, para o tipo desejado.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Suponha que a seguinte classe seja definida: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));
    }
}

O exemplo a seguir ilustra as conversões dinâmicas explícitas: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

A melhor conversão de o para C é encontrada em tempo de compilação para ser uma conversão de referência explícita.The best conversion of o to C is found at compile-time to be an explicit reference conversion. Isso falha em tempo de execução, porque "1" não é, na verdade, uma C .This fails at run-time, because "1" is not in fact a C. A conversão de d para C no entanto, como uma conversão dinâmica explícita, é suspensa para tempo de execução, onde uma conversão definida pelo usuário do tipo de tempo de execução de d -- string --para C é encontrada e é bem sucedido.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.

Conversões explícitas envolvendo parâmetros de tipoExplicit conversions involving type parameters

Existem as seguintes conversões explícitas para um determinado parâmetro de tipo T :The following explicit conversions exist for a given type parameter T:

  • Da classe base efetiva C de T para T e de qualquer classe base de C para T .From the effective base class C of T to T and from any base class of C to T. Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão não boxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. Caso contrário, a conversão é executada como uma conversão de referência explícita ou conversão de identidade.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • De qualquer tipo de interface para T .From any interface type to T. Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão não boxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. Caso contrário, a conversão é executada como uma conversão de referência explícita ou conversão de identidade.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • De T para qualquer interface_type I fornecido, ainda não há uma conversão implícita de T para I .From T to any interface_type I provided there is not already an implicit conversion from T to I. Em tempo de execução, se T for um tipo de valor, a conversão será executada como uma conversão boxing seguida de uma conversão de referência explícita.At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. Caso contrário, a conversão é executada como uma conversão de referência explícita ou conversão de identidade.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • De um parâmetro de tipo U para T , fornecido T depende de U (restrições de parâmetro detipo).From a type parameter U to T, provided T depends on U (Type parameter constraints). Em tempo de execução, se U for um tipo de valor, será, T U necessariamente, o mesmo tipo e nenhuma conversão será executada.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. Caso contrário, se T for um tipo de valor, a conversão será executada como uma conversão não boxing.Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. Caso contrário, a conversão é executada como uma conversão de referência explícita ou conversão de identidade.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

Se T for conhecido como um tipo de referência, as conversões acima serão todas classificadas como conversões de referência explícita (conversões de referência explícitas).If T is known to be a reference type, the conversions above are all classified as explicit reference conversions (Explicit reference conversions). Se T não for conhecido como um tipo de referência, as conversões acima serão classificadas como conversões não Boxing (conversões unboxing).If T is not known to be a reference type, the conversions above are classified as unboxing conversions (Unboxing conversions).

As regras acima não permitem uma conversão explícita direta de um parâmetro de tipo irrestrito para um tipo que não seja de interface, o que pode ser surpreendente.The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. A razão para essa regra é evitar confusão e tornar a semântica dessas conversões clara.The reason for this rule is to prevent confusion and make the semantics of such conversions clear. Por exemplo, considere a seguinte declaração:For example, consider the following declaration:

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

Se a conversão explícita direta de t para int fosse permitida, uma delas poderia esperar que X<int>.F(7) retornasse  7L .If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7) would return 7L. No entanto, isso não ocorre porque as conversões numéricas padrão só são consideradas quando os tipos são conhecidos como numéricos no tempo de associação.However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. Para tornar a semântica clara, o exemplo acima deve ser escrito em vez disso: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
    }
}

Agora, esse código será compilado, mas a execução X<int>.F(7) geraria uma exceção em tempo de execução, pois um Boxed int não pode ser convertido diretamente em um 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.

Conversões explícitas definidas pelo usuárioUser-defined explicit conversions

Uma conversão explícita definida pelo usuário consiste em uma conversão explícita padrão opcional, seguida pela execução de um operador de conversão implícita ou explícita definido pelo usuário, seguido por outra conversão opcional explícita padrão.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. As regras exatas para avaliar conversões explícitas definidas pelo usuário são descritas em processamento de conversões explícitas definidas pelo usuário.The exact rules for evaluating user-defined explicit conversions are described in Processing of user-defined explicit conversions.

Conversões padrãoStandard conversions

As conversões padrão são aquelas conversões predefinidas que podem ocorrer como parte de uma conversão definida pelo usuário.The standard conversions are those pre-defined conversions that can occur as part of a user-defined conversion.

Conversões implícitas padrãoStandard implicit conversions

As conversões implícitas a seguir são classificadas como conversões implícitas padrão:The following implicit conversions are classified as standard implicit conversions:

As conversões implícitas padrão excluem especificamente conversões implícitas definidas pelo usuário.The standard implicit conversions specifically exclude user-defined implicit conversions.

Conversões explícitas padrãoStandard explicit conversions

As conversões explícitas padrão são todas as conversões implícitas padrão mais o subconjunto das conversões explícitas para as quais existe uma conversão implícita padrão oposta.The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. Em outras palavras, se existir uma conversão implícita padrão de um tipo A para um tipo B , uma conversão explícita padrão existirá de tipo A para tipo B e de tipo B para tipo 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.

Conversões definidas pelo usuárioUser-defined conversions

O C# permite que as conversões implícitas e explícitas predefinidas sejam aumentadas por conversões definidas pelo usuário.C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. Conversões definidas pelo usuário são introduzidas pela declaração de operadores de conversão (operadores de conversão) em tipos de classe e struct.User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

Conversões permitidas definidas pelo usuárioPermitted user-defined conversions

O C# permite que apenas determinadas conversões definidas pelo usuário sejam declaradas.C# permits only certain user-defined conversions to be declared. Em particular, não é possível redefinir uma conversão implícita ou explícita já existente.In particular, it is not possible to redefine an already existing implicit or explicit conversion.

Para um determinado tipo de origem S e tipo T de destino, se S ou T forem tipos anuláveis, avise S0 e T0 faça referência aos seus tipos subjacentes, caso contrário, S0 e T0 sejam iguais a S e 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. Uma classe ou estrutura tem permissão para declarar uma conversão de um tipo de origem S para um tipo de destino T somente se todas as seguintes opções forem verdadeiras: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 e T0 são tipos diferentes.S0 and T0 are different types.
  • S0Ou T0 é o tipo de classe ou struct no qual a declaração do operador ocorre.Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • Nem S0 nem T0 é um interface_type.Neither S0 nor T0 is an interface_type.
  • Excluindo conversões definidas pelo usuário, uma conversão não existe de S ou para T T S .Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

As restrições que se aplicam a conversões definidas pelo usuário são discutidas mais detalhadamente nos operadores de conversão.The restrictions that apply to user-defined conversions are discussed further in Conversion operators.

Operadores de conversão levantadosLifted conversion operators

Dado um operador de conversão definido pelo usuário que converte de um tipo de valor não anulável S para um tipo de valor não anulável T , existe um operador de conversão levantado que converte de S? para 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?. Esse operador de conversão levantado executa um desempacotamento do S? para S seguido pela conversão definida pelo usuário de S para T seguida por um encapsulamento de T para T? , exceto que um valor nulo é S? convertido diretamente em um valor nulo 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?.

Um operador de conversão elevado tem a mesma classificação implícita ou explícita que seu operador de conversão subjacente definido pelo usuário.A lifted conversion operator has the same implicit or explicit classification as its underlying user-defined conversion operator. O termo "conversão definida pelo usuário" aplica-se ao uso de operadores de conversão que foram definidos pelo usuário e com elevação.The term "user-defined conversion" applies to the use of both user-defined and lifted conversion operators.

Avaliação de conversões definidas pelo usuárioEvaluation of user-defined conversions

Uma conversão definida pelo usuário converte um valor de seu tipo, chamado de tipo de origem _, para outro tipo, chamado de _tipo de destino*.A user-defined conversion converts a value from its type, called the source type _, to another type, called the _target type*. Avaliação de um centro de conversão definido pelo usuário para encontrar o _ mais específico* operador de conversão definido pelo usuário para os tipos de origem e destino específicos.Evaluation of a user-defined conversion centers on finding the _ most specific* user-defined conversion operator for the particular source and target types. Essa determinação é dividida em várias etapas:This determination is broken into several steps:

  • Localizando o conjunto de classes e structs dos quais operadores de conversão definidos pelo usuário serão considerados.Finding the set of classes and structs from which user-defined conversion operators will be considered. Esse conjunto consiste no tipo de origem e suas classes base, e o tipo de destino e suas classes base (com as suposições implícitas que somente classes e structs podem declarar operadores definidos pelo usuário e que não têm classes 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 os fins desta etapa, se o tipo de origem ou de destino for um nullable_type, seu tipo subjacente será usado em seu lugar.For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
  • Desse conjunto de tipos, determinando quais operadores de conversão levantados e definidos pelo usuário são aplicáveis.From that set of types, determining which user-defined and lifted conversion operators are applicable. Para que um operador de conversão seja aplicável, deve ser possível executar uma conversão padrão (conversões padrão) do tipo de origem para o tipo de operando do operador e deve ser possível executar uma conversão padrão do tipo de resultado do operador para o 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.
  • Do conjunto de operadores aplicáveis definidos pelo usuário, determinando qual operador não é ambíguomente o mais específico.From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. Em termos gerais, o operador mais específico é o operador cujo tipo de operando é "mais próximo" do tipo de origem e cujo tipo de resultado é "mais próximo" ao 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. Os operadores de conversão definidos pelo usuário são preferenciais em relação aos operadores de conversão levantados.User-defined conversion operators are preferred over lifted conversion operators. As regras exatas para estabelecer o operador de conversão mais específico definido pelo usuário são definidas nas seções a seguir.The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

Depois que um operador de conversão definido pelo usuário mais específico tiver sido identificado, a execução real da conversão definida pelo usuário envolverá até três etapas:Once a most specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • Primeiro, se necessário, executando uma conversão padrão do tipo de origem para o tipo de operando do operador de conversão definido pelo usuário ou levantado.First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
  • Em seguida, invocando o operador de conversão definido pelo usuário ou elevação para executar a conversão.Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • Por fim, se necessário, executar uma conversão padrão do tipo de resultado do operador de conversão definido pelo usuário ou de forma elevada para o 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.

A avaliação de uma conversão definida pelo usuário nunca envolve mais de um operador de conversão mais definido pelo usuário ou levantado.Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. Em outras palavras, uma conversão de tipo S para tipo T nunca executará primeiro uma conversão definida pelo usuário de S para X e, em seguida, executará uma conversão definida pelo usuário de X para 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.

As definições exatas de avaliação de conversões implícitas ou explícitas definidas pelo usuário são dadas nas seções a seguir.Exact definitions of evaluation of user-defined implicit or explicit conversions are given in the following sections. As definições fazem uso dos seguintes termos:The definitions make use of the following terms:

  • Se uma conversão implícita padrão (conversões implícitas padrão) existir de um tipo A para um tipo B , e se nem A B for interface_type s, A será dito que é * englobado por _ B e B é dito como _ ** * 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_type s, then A is said to be encompassed by _ B, and B is said to _ encompass A.
  • O tipo mais abrangente em um conjunto de tipos é aquele que abrange todos os outros tipos no conjunto.The most encompassing type in a set of types is the one type that encompasses all other types in the set. Se nenhum tipo único abranger todos os outros tipos, o conjunto não terá mais de abranger o tipo.If no single type encompasses all other types, then the set has no most encompassing type. Em termos mais intuitivos, o tipo mais abrangente é o tipo "maior" no conjunto — o tipo para o qual cada um dos outros tipos pode ser convertido implicitamente.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.
  • O tipo mais abrangente em um conjunto de tipos é aquele que é abrangedo por todos os outros tipos no conjunto.The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. Se nenhum tipo único for abrangedo por todos os outros tipos, o conjunto não terá o tipo mais abrangedo.If no single type is encompassed by all other types, then the set has no most encompassed type. Em termos mais intuitivos, o tipo mais abrangente é o tipo "menor" no conjunto — aquele tipo que pode ser convertido implicitamente em cada um dos outros 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.

Processamento de conversões implícitas definidas pelo usuárioProcessing of user-defined implicit conversions

Uma conversão implícita definida pelo usuário do tipo S para T o tipo é processada da seguinte maneira:A user-defined implicit conversion from type S to type T is processed as follows:

  • Determine os tipos S0 e T0 .Determine the types S0 and T0. If S ou T são tipos anuláveis, S0 e T0 são seus tipos subjacentes, caso contrário, S0 e T0 são iguais a S e 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.
  • Localize o conjunto de tipos, D , do qual os operadores de conversão definidos pelo usuário serão considerados.Find the set of types, D, from which user-defined conversion operators will be considered. Esse conjunto consiste em S0 (if S0 é uma classe ou struct), as classes base de S0 (if S0 é uma classe) e T0 (if T0 é uma Class ou 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).
  • Localize o conjunto de operadores de conversão aplicáveis definidos pelo usuário e com elevação, U .Find the set of applicable user-defined and lifted conversion operators, U. Esse conjunto consiste nos operadores de conversão implícitas definidos pelo usuário e levantados declarados pelas classes ou estruturas no D que são convertidas de um tipo que abrange S um tipo que é abrangedo 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. Se U estiver vazio, a conversão será indefinida e ocorrerá um erro de tempo de compilação.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Localize o tipo de fonte mais específico, SX , dos operadores em U :Find the most specific source type, SX, of the operators in U:
    • Se qualquer um dos operadores em U converter de S , SX for S .If any of the operators in U convert from S, then SX is S.
    • Caso contrário, SX é o tipo mais abrangente no conjunto combinado de tipos de origem dos operadores no U .Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. Se não for possível encontrar exatamente um tipo mais abrangente, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Localize o tipo de destino mais específico, TX , dos operadores em U :Find the most specific target type, TX, of the operators in U:
    • Se qualquer um dos operadores em U converter para T , TX for T .If any of the operators in U convert to T, then TX is T.
    • Caso contrário, TX é o tipo mais abrangente no conjunto combinado de tipos de destino dos operadores no U .Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. Se não for possível encontrar exatamente um tipo mais abrangente, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Encontre o operador de conversão mais específico:Find the most specific conversion operator:
    • Se U contiver exatamente um operador de conversão definido pelo usuário que converte de SX para TX , esse será o operador de conversão mais 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.
    • Caso contrário, se U contiver exatamente um operador de conversão levantado que converta de SX para TX , esse será o operador de conversão mais 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.
    • Caso contrário, a conversão é ambígua e ocorre um erro de tempo de compilação.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Por fim, aplique a conversão:Finally, apply the conversion:
    • Se S não for SX , uma conversão implícita padrão de S para SX será executada.If S is not SX, then a standard implicit conversion from S to SX is performed.
    • O operador de conversão mais específico é chamado para converter de SX para TX .The most specific conversion operator is invoked to convert from SX to TX.
    • Se TX não for T , uma conversão implícita padrão de TX para T será executada.If TX is not T, then a standard implicit conversion from TX to T is performed.

Processamento de conversões explícitas definidas pelo usuárioProcessing of user-defined explicit conversions

Uma conversão explícita definida pelo usuário do tipo S para T o tipo é processada da seguinte maneira:A user-defined explicit conversion from type S to type T is processed as follows:

  • Determine os tipos S0 e T0 .Determine the types S0 and T0. If S ou T são tipos anuláveis, S0 e T0 são seus tipos subjacentes, caso contrário, S0 e T0 são iguais a S e 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.
  • Localize o conjunto de tipos, D , do qual os operadores de conversão definidos pelo usuário serão considerados.Find the set of types, D, from which user-defined conversion operators will be considered. Esse conjunto consiste em S0 (se S0 for uma classe ou struct), as classes base de S0 (se S0 for uma classe), T0 (se T0 for uma classe ou estrutura) e as classes base de T0 (se T0 for uma classe).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).
  • Localize o conjunto de operadores de conversão aplicáveis definidos pelo usuário e com elevação, U .Find the set of applicable user-defined and lifted conversion operators, U. Esse conjunto consiste nos operadores de conversão implícitos ou explícitos definidos pelo usuário, declarados pelas classes ou structs no D que são convertidos de um tipo que abrange ou é derivado de S para um tipo que abrange ou abrangedo pelo 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. Se U estiver vazio, a conversão será indefinida e ocorrerá um erro de tempo de compilação.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Localize o tipo de fonte mais específico, SX , dos operadores em U :Find the most specific source type, SX, of the operators in U:
    • Se qualquer um dos operadores em U converter de S , SX for S .If any of the operators in U convert from S, then SX is S.
    • Caso contrário, se qualquer um dos operadores em U converter dos tipos que englobam S , SX será o tipo mais abrangedo no conjunto combinado de tipos de origem desses 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. Se nenhum tipo mais abrangedo puder ser encontrado, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
    • Caso contrário, SX é o tipo mais abrangente no conjunto combinado de tipos de origem dos operadores no U .Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. Se não for possível encontrar exatamente um tipo mais abrangente, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Localize o tipo de destino mais específico, TX , dos operadores em U :Find the most specific target type, TX, of the operators in U:
    • Se qualquer um dos operadores em U converter para T , TX for T .If any of the operators in U convert to T, then TX is T.
    • Caso contrário, se qualquer um dos operadores em U converter para tipos que são incluídos pelo T , TX será o tipo mais abrangente no conjunto combinado de tipos de destino desses 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. Se não for possível encontrar exatamente um tipo mais abrangente, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
    • Caso contrário, TX é o tipo mais abrangedo no conjunto combinado de tipos de destino dos operadores no U .Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. Se nenhum tipo mais abrangedo puder ser encontrado, a conversão será ambígua e ocorrerá um erro de tempo de compilação.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
  • Encontre o operador de conversão mais específico:Find the most specific conversion operator:
    • Se U contiver exatamente um operador de conversão definido pelo usuário que converte de SX para TX , esse será o operador de conversão mais 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.
    • Caso contrário, se U contiver exatamente um operador de conversão levantado que converta de SX para TX , esse será o operador de conversão mais 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.
    • Caso contrário, a conversão é ambígua e ocorre um erro de tempo de compilação.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Por fim, aplique a conversão:Finally, apply the conversion:
    • Se S não for SX , uma conversão explícita padrão de S para SX será executada.If S is not SX, then a standard explicit conversion from S to SX is performed.
    • O operador de conversão mais específico definido pelo usuário é chamado para converter de SX para TX .The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • Se TX não for T , uma conversão explícita padrão de TX para T será executada.If TX is not T, then a standard explicit conversion from TX to T is performed.

Conversões de função anônimaAnonymous function conversions

Uma anonymous_method_expression ou lambda_expression é classificada como uma função anônima (expressões de função anônimas).An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). A expressão não tem um tipo, mas pode ser convertida implicitamente em um tipo de delegado ou tipo de árvore de expressão compatível.The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. Especificamente, uma função anônima F é compatível com um tipo delegado D fornecido:Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Se F contiver um anonymous_function_signature, D e F terá o mesmo número de parâmetros.If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Se não F contiver um anonymous_function_signature, D poderá ter zero ou mais parâmetros de qualquer tipo, desde que nenhum parâmetro de D tenha o 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.
  • Se o F tiver uma lista de parâmetros tipados explicitamente, cada parâmetro no D terá o mesmo tipo e modificadores que o parâmetro correspondente no 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.
  • Se F o tiver uma lista de parâmetros Tipados implicitamente, o D não terá ref out parâmetros ou.If F has an implicitly typed parameter list, D has no ref or out parameters.
  • Se o corpo de F for uma expressão e D tiver um tipo de void retorno ou F for Async e D tiver o tipo de retorno Task , quando cada parâmetro de F for dado o tipo do parâmetro correspondente no D , o corpo de F será uma expressão válida (wrt Expressions) que seria permitida como uma statement_expression (instruções de expressão).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).
  • Se o corpo de F for um bloco de instrução e D tiver um void tipo de retorno ou F for Async e D tiver o tipo de retorno Task , quando cada parâmetro de F for dado o tipo do parâmetro correspondente no D , o corpo de F será um bloco de instrução válido ( blocosWRT) em que nenhuma return instrução especifica uma expressão.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.
  • Se o corpo de F for uma expressão, e F for não Async e D tiver um tipo de retorno não void T , ou F for Async e D tiver um tipo de retorno Task<T> , quando cada parâmetro de F for dado o tipo do parâmetro correspondente no D , o corpo de F será uma expressão válida (WRT Expressions) que é implicitamente conversível para 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.
  • Se o corpo de F for um bloco de instrução, e F é não Async e D tem um tipo de retorno não void T , ou F é Async e D tem um tipo de retorno Task<T> , quando cada parâmetro de F recebe o tipo do parâmetro correspondente no D , o corpo de F é um bloco de instrução válido ( blocosWRT) com um ponto de extremidade não acessível no qual cada return instrução especifica uma expressão que é implicitamente conversível para 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 fins de brevidade, esta seção usa a forma abreviada para os tipos de tarefa Task e Task<T> (funções assíncronas).For the purpose of brevity, this section uses the short form for the task types Task and Task<T> (Async functions).

Uma expressão lambda F é compatível com um tipo de árvore de expressão Expression<D> se F for compatível com o tipo delegado D .A lambda expression F is compatible with an expression tree type Expression<D> if F is compatible with the delegate type D. Observe que isso não se aplica a métodos anônimos, somente expressões lambda.Note that this does not apply to anonymous methods, only lambda expressions.

Determinadas expressões lambda não podem ser convertidas em tipos de árvore de expressões: mesmo que a conversão exista, ela falhará em tempo de compilação.Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. Esse é o caso se a expressão lambda:This is the case if the lambda expression:

  • Tem um corpo de blocoHas a block body
  • Contém operadores de atribuição simples ou compostosContains simple or compound assignment operators
  • Contém uma expressão vinculada dinamicamenteContains a dynamically bound expression
  • É AsyncIs async

Os exemplos a seguir usam um tipo de delegado genérico Func<A,R> que representa uma função que usa um argumento do tipo A e retorna um valor do 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);

Nas atribuiçõesIn 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

os tipos de parâmetro e de retorno de cada função anônima são determinados do tipo da variável à qual a função anônima é atribuída.the parameter and return types of each anonymous function are determined from the type of the variable to which the anonymous function is assigned.

A primeira atribuição converte com êxito a função anônima no tipo delegado Func<int,int> porque, quando x é o tipo fornecido int , x+1 é uma expressão válida que é implicitamente conversível para o 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.

Da mesma forma, a segunda atribuição converte com êxito a função anônima no tipo delegado Func<int,double> porque o resultado de x+1 (do tipo int ) é implicitamente conversível para o 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.

No entanto, a terceira atribuição é um erro de tempo de compilação porque, quando x é determinado tipo double , o resultado de x+1 (do tipo double ) não é implicitamente conversível para o 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.

A quarta atribuição converte com êxito a função Async anônima no tipo delegado Func<int, Task<int>> porque o resultado de x+1 (do tipo int ) é implicitamente conversível para o tipo de resultado int do tipo de tarefa 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>.

As funções anônimas podem influenciar a resolução de sobrecarga e participar da inferência de tipos.Anonymous functions may influence overload resolution, and participate in type inference. Consulte membros da função para obter mais detalhes.See Function members for further details.

Avaliação de conversões de função anônima para tipos delegadosEvaluation of anonymous function conversions to delegate types

A conversão de uma função anônima em um tipo delegate produz uma instância delegada que faz referência à função anônima e ao conjunto (possivelmente vazio) de variáveis externas capturadas que estão ativas no momento da avaliaçã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. Quando o delegado é invocado, o corpo da função anônima é executado.When the delegate is invoked, the body of the anonymous function is executed. O código no corpo é executado usando o conjunto de variáveis externas capturadas referenciadas pelo delegado.The code in the body is executed using the set of captured outer variables referenced by the delegate.

A lista de invocação de um delegado produzido por uma função anônima contém uma única entrada.The invocation list of a delegate produced from an anonymous function contains a single entry. O objeto de destino exato e o método de destino do delegado não são especificados.The exact target object and target method of the delegate are unspecified. Em particular, ele não é especificado se o objeto de destino do delegado é null , o this valor do membro da função delimitadora ou algum outro 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.

Conversões de funções anônimas, semanticamente idênticas com o mesmo conjunto (possivelmente vazio) de instâncias de variáveis externas capturadas para os mesmos tipos delegados, são permitidas (mas não obrigatórias) para retornar a mesma instância 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. O termo semanticamente idêntico é usado aqui para significar que a execução das funções anônimas irá, em todos os casos, produzir os mesmos efeitos, considerando os mesmos 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. Essa regra permite que um código como o seguinte seja otimizado.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));
        ...
    }
}

Como os dois delegados de função anônimas têm o mesmo conjunto (vazio) de variáveis externas capturadas e, como as funções anônimas são semanticamente idênticas, o compilador tem permissão para fazer com que os delegados se refiram ao mesmo 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. Na verdade, o compilador tem permissão para retornar a mesma instância de delegado de ambas as expressões de função anônimas.Indeed, the compiler is permitted to return the very same delegate instance from both anonymous function expressions.

Avaliação de conversões de função anônima para tipos de árvore de expressãoEvaluation of anonymous function conversions to expression tree types

A conversão de uma função anônima em um tipo de árvore de expressão produz uma árvore de expressão (tipos de árvore de expressão).Conversion of an anonymous function to an expression tree type produces an expression tree (Expression tree types). Mais precisamente, a avaliação da conversão da função anônima leva à construção de uma estrutura de objeto que representa a estrutura da própria função 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. A estrutura precisa da árvore de expressão, bem como o processo exato para criá-la, são definidas para implementação.The precise structure of the expression tree, as well as the exact process for creating it, are implementation defined.

Exemplo de implementaçãoImplementation example

Esta seção descreve uma possível implementação de conversões de funções anônimas em termos de outras construções de C#.This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. A implementação descrita aqui se baseia nos mesmos princípios usados pelo compilador do Microsoft C#, mas não é, de maneira alguma, uma implementação obrigatória, nem é a única possível.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. Ele apenas menciona conversões em árvores de expressão, pois a semântica exata está fora do escopo desta especificação.It only briefly mentions conversions to expression trees, as their exact semantics are outside the scope of this specification.

O restante desta seção fornece vários exemplos de código que contém funções anônimas com características diferentes.The remainder of this section gives several examples of code that contains anonymous functions with different characteristics. Para cada exemplo, é fornecida uma tradução correspondente ao código que usa apenas outras construções C#.For each example, a corresponding translation to code that uses only other C# constructs is provided. Nos exemplos, o identificador D é assumido por representar o seguinte tipo de delegado:In the examples, the identifier D is assumed by represent the following delegate type:

public delegate void D();

A forma mais simples de uma função anônima é aquela que captura nenhuma variável externa:The simplest form of an anonymous function is one that captures no outer variables:

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

Isso pode ser convertido em uma instanciação de delegado que faz referência a um método estático gerado pelo compilador no qual o código da função anônima é colocado: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");
    }
}

No exemplo a seguir, a função anônima faz referência a membros da instância 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); };
    }
}

Isso pode ser convertido em um método de instância gerado pelo compilador que contém o código da função 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);
    }
}

Neste exemplo, a função anônima captura uma variável local:In this example, the anonymous function captures a local variable:

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

O tempo de vida da variável local agora deve ser estendido para pelo menos o tempo de vida do delegado da função anônima.The lifetime of the local variable must now be extended to at least the lifetime of the anonymous function delegate. Isso pode ser obtido por meio da "guindaste" da variável local em um campo de uma classe gerada pelo compilador.This can be achieved by "hoisting" the local variable into a field of a compiler generated class. A instanciação da variável local (instanciação de variáveis locais) corresponde à criação de uma instância da classe gerada pelo compilador e o acesso à variável local corresponde ao acesso a um campo na instância da classe gerada pelo 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. Além disso, a função anônima torna-se um método de instância da classe gerada pelo 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 fim, a função anônima a seguir captura this , bem como duas variáveis locais com tempos de vida diferentes: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); };
        }
    }
}

Aqui, uma classe gerada pelo compilador é criada para cada bloco de instrução no qual os locais são capturados, de modo que os locais nos diferentes blocos possam ter tempos de vida independentes.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. Uma instância do __Locals2 , a classe gerada pelo compilador para o bloco de instrução interna, contém a variável local z e um campo que faz referência a uma instância do __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. Uma instância do __Locals1 , a classe gerada pelo compilador para o bloco de instrução externa, contém a variável local y e um campo que faz referência this ao membro da função de circunscrição.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. Com essas estruturas de dados, é possível alcançar todas as variáveis externas capturadas por meio de uma instância do __Local2 e o código da função anônima pode, portanto, ser implementado como um método de instância dessa classe.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);
        }
    }
}

A mesma técnica aplicada aqui para capturar variáveis locais também pode ser usada ao converter funções anônimas em árvores de expressão: referências aos objetos gerados pelo compilador podem ser armazenadas na árvore de expressão e o acesso às variáveis locais pode ser representado como acessos de campo nesses 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. A vantagem dessa abordagem é que ela permite que as variáveis locais "levantadas" sejam compartilhadas entre delegados e árvores de expressão.The advantage of this approach is that it allows the "lifted" local variables to be shared between delegates and expression trees.

Conversões de grupo de métodosMethod group conversions

Uma conversão implícita (conversões implícitas) existe de um grupo de métodos (classificações de expressão) para um tipo de delegado compatível.An implicit conversion (Implicit conversions) exists from a method group (Expression classifications) to a compatible delegate type. Dado um tipo delegado D e uma expressão E que é classificada como um grupo de métodos, uma conversão implícita existe de E para D se E contiver pelo menos um método aplicável em seu formato normal (membro de função aplicável) a uma lista de argumentos construída pelo uso dos tipos de parâmetro e modificadores de D , conforme descrito a seguir.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.

O aplicativo de tempo de compilação de uma conversão de um grupo de métodos E para um tipo delegado D é descrito a seguir.The compile-time application of a conversion from a method group E to a delegate type D is described in the following. Observe que a existência de uma conversão implícita de E para não D garante que o aplicativo de tempo de compilação da conversão terá sucesso sem erros.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.

  • Um único método M é selecionado, correspondendo a uma invocação de método (invocações de método) do formulário E(A) , com as seguintes modificações:A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
    • A lista A de argumentos é uma lista de expressões, cada uma classificada como variável e com o tipo e o modificador ( ref ou out ) do parâmetro correspondente no 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.
    • Os métodos candidatos considerados são apenas os métodos que são aplicáveis em seu formato normal (membro de função aplicável), não aqueles aplicáveis apenas em sua 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.
  • Se o algoritmo das invocações de método produzir um erro, ocorrerá um erro de tempo de compilação.If the algorithm of Method invocations produces an error, then a compile-time error occurs. Caso contrário, o algoritmo produz um único método melhor M com o mesmo número de parâmetros que D e a conversão é considerada como existente.Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
  • O método selecionado M deve ser compatível (delegar compatibilidade) com o tipo delegado D ou, caso contrário, ocorrerá um erro de tempo de compilação.The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
  • Se o método selecionado M for um método de instância, a expressão de instância associada a E determinará o objeto de destino do delegado.If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
  • Se o método selecionado M for um método de extensão indicado por meio de um acesso de membro em uma expressão de instância, essa expressão de instância determinará o objeto de destino do 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.
  • O resultado da conversão é um valor do tipo  D , ou seja, um delegado recém-criado que se refere ao método selecionado e ao objeto de destino.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.
  • Observe que esse processo pode levar à criação de um delegado para um método de extensão, se o algoritmo das invocações de método não conseguir encontrar um método de instância, mas tiver êxito no processamento da invocação de E(A) como uma invocação de método de extensão (invocações de método de extensão).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). Um delegado criado então captura o método de extensão, bem como seu primeiro argumento.A delegate thus created captures the extension method as well as its first argument.

O exemplo a seguir demonstra as conversões 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

    }
}

A atribuição para d1 converter implicitamente o grupo de métodos F em um valor do tipo D1 .The assignment to d1 implicitly converts the method group F to a value of type D1.

A atribuição para d2 mostra como é possível criar um delegado para um método que tenha tipos de parâmetro menos derivados (contravariant) e um tipo de retorno mais derivado (Covariance).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.

A atribuição para d3 mostra como nenhuma conversão existe se o método não for aplicável.The assignment to d3 shows how no conversion exists if the method is not applicable.

A atribuição para d4 mostra como o método deve ser aplicável em seu formato normal.The assignment to d4 shows how the method must be applicable in its normal form.

A atribuição para d5 mostra como os tipos de parâmetro e de retorno do delegado e do método têm permissão para diferir apenas para tipos de referência.The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

Assim como acontece com todas as outras conversões implícitas e explícitas, o operador cast pode ser usado para executar explicitamente uma conversão de grupo de métodos.As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. Portanto, o exemploThus, the example

object obj = new EventHandler(myDialog.OkClick);

em vez disso, poderia ser escritocould instead be written

object obj = (EventHandler)myDialog.OkClick;

Os grupos de métodos podem influenciar a resolução de sobrecarga e participar da inferência de tipos.Method groups may influence overload resolution, and participate in type inference. Consulte membros da função para obter mais detalhes.See Function members for further details.

A avaliação de tempo de execução de uma conversão de grupo de métodos procede da seguinte maneira:The run-time evaluation of a method group conversion proceeds as follows:

  • Se o método selecionado em tempo de compilação for um método de instância, ou for um método de extensão que é acessado como um método de instância, o objeto de destino do delegado é determinado da expressão de instância associada a 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:
    • A expressão de instância é avaliada.The instance expression is evaluated. Se essa avaliação causar uma exceção, nenhuma etapa adicional será executada.If this evaluation causes an exception, no further steps are executed.
    • Se a expressão de instância for de um reference_type, o valor calculado pela expressão de instância se tornará o objeto de destino.If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. Se o método selecionado for um método de instância e o objeto de destino for null , um System.NullReferenceException será lançado e nenhuma etapa adicional será executada.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.
    • Se a expressão de instância for de um value_type, uma operação Boxing (conversões Boxing) será executada para converter o valor em um objeto e esse objeto se tornará o 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.
  • Caso contrário, o método selecionado faz parte de uma chamada de método estático e o objeto de destino do delegado é null .Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
  • Uma nova instância do tipo delegado D é alocada.A new instance of the delegate type D is allocated. Se não houver memória suficiente disponível para alocar a nova instância, um System.OutOfMemoryException será lançado e nenhuma etapa adicional será executada.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • A nova instância de delegado é inicializada com uma referência ao método que foi determinado em tempo de compilação e uma referência ao objeto de destino calculado acima.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.