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
edynamic
são considerados equivalentes, há uma conversão de identidade entreobject
e edynamic
entre os tipos construídos que são iguais ao substituir todas as ocorrências dedynamic
porobject
.Becauseobject
anddynamic
are considered equivalent there is an identity conversion betweenobject
anddynamic
, and between constructed types that are the same when replacing all occurrences ofdynamic
withobject
.
Conversões numéricas implícitasImplicit numeric conversions
As conversões numéricas implícitas são:The implicit numeric conversions are:
- De
sbyte
parashort
,int
,long
,float
,double
oudecimal
.Fromsbyte
toshort
,int
,long
,float
,double
, ordecimal
. - De
byte
parashort
,ushort
,,,,,int
uint
long
ulong
float
,double
oudecimal
.Frombyte
toshort
,ushort
,int
,uint
,long
,ulong
,float
,double
, ordecimal
. - De
short
paraint
,long
,float
,double
oudecimal
.Fromshort
toint
,long
,float
,double
, ordecimal
. - De
ushort
paraint
,,,,,uint
long
ulong
float
double
oudecimal
.Fromushort
toint
,uint
,long
,ulong
,float
,double
, ordecimal
. - Do
int
paralong
,float
,double
oudecimal
.Fromint
tolong
,float
,double
, ordecimal
. - De
uint
paralong
,ulong
,float
,double
oudecimal
.Fromuint
tolong
,ulong
,float
,double
, ordecimal
. - Do
long
parafloat
,double
oudecimal
.Fromlong
tofloat
,double
, ordecimal
. - Do
ulong
parafloat
,double
oudecimal
.Fromulong
tofloat
,double
, ordecimal
. - De
char
paraushort
,int
,,,,,uint
long
ulong
float
double
oudecimal
.Fromchar
toushort
,int
,uint
,long
,ulong
,float
,double
, ordecimal
. - De
float
adouble
.Fromfloat
todouble
.
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?
paraT?
.An implicit conversion fromS?
toT?
. - Uma conversão implícita de
S
paraT?
.An implicit conversion fromS
toT?
.
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?
paraT?
:If the nullable conversion is fromS?
toT?
:- Se o valor de origem for NULL (a
HasValue
propriedade é false), o resultado será o valor nulo do tipoT?
.If the source value is null (HasValue
property is false), the result is the null value of typeT?
. - Caso contrário, a conversão é avaliada como um desempacotamento de
S?
paraS
, seguida pela conversão subjacente deS
paraT
, seguida por um encapsulamento (tipos anuláveis) deT
paraT?
.Otherwise, the conversion is evaluated as an unwrapping fromS?
toS
, followed by the underlying conversion fromS
toT
, followed by a wrapping (Nullable types) fromT
toT?
.
- Se o valor de origem for NULL (a
Se a conversão anulável for de
S
paraT?
, a conversão será avaliada como a conversão subjacente deS
paraT
seguida de um encapsulamento deT
paraT?
.If the nullable conversion is fromS
toT?
, the conversion is evaluated as the underlying conversion fromS
toT
followed by a wrapping fromT
toT?
.
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
edynamic
.From any reference_type toobject
anddynamic
. - De qualquer class_type
S
a qualquer class_typeT
, fornecidaS
é derivada deT
.From any class_typeS
to any class_typeT
, providedS
is derived fromT
. - De qualquer class_type
S
a qualquer interface_typeT
, fornecidaS
implementaT
.From any class_typeS
to any interface_typeT
, providedS
implementsT
. - De qualquer interface_type
S
a qualquer interface_typeT
, fornecidaS
é derivada deT
.From any interface_typeS
to any interface_typeT
, providedS
is derived fromT
. - De um array_type
S
com um tipo de elementoSE
para um array_typeT
com um tipo de elementoTE
, desde que todas as seguintes opções sejam verdadeiras:From an array_typeS
with an element typeSE
to an array_typeT
with an element typeTE
, provided all of the following are true:S
eT
difere somente no tipo de elemento.S
andT
differ only in element type. Em outras palavras,S
eT
têm o mesmo número de dimensões.In other words,S
andT
have the same number of dimensions.- Ambos
SE
eTE
são reference_type s.BothSE
andTE
are reference_type s. - Existe uma conversão de referência implícita de
SE
paraTE
.An implicit reference conversion exists fromSE
toTE
.
- De qualquer array_type para
System.Array
o e as interfaces que ele implementa.From any array_type toSystem.Array
and the interfaces it implements. - De um tipo de matriz unidimensional
S[]
paraSystem.Collections.Generic.IList<T>
o e suas interfaces base, desde que haja uma conversão implícita de identidade ou referência deS
paraT
.From a single-dimensional array typeS[]
toSystem.Collections.Generic.IList<T>
and its base interfaces, provided that there is an implicit identity or reference conversion fromS
toT
. - De qualquer delegate_type para
System.Delegate
o e as interfaces que ele implementa.From any delegate_type toSystem.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_typeT0
eT0
tiver uma conversão de identidade paraT
.From any reference_type to a reference_typeT
if it has an implicit identity or reference conversion to a reference_typeT0
andT0
has an identity conversion toT
. - 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 delegadoT0
eT0
for conversível (conversão de variância) paraT
.From any reference_type to an interface or delegate typeT
if it has an implicit identity or reference conversion to an interface or delegate typeT0
andT0
is variance-convertible (Variance conversion) toT
. - 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 boxedT
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 tiposbyte
,byte
,,, ou,short
desde queushort
uint
ulong
o valor da constant_expression esteja dentro do intervalo do tipo de destino.A constant_expression (Constant expressions) of typeint
can be converted to typesbyte
,byte
,short
,ushort
,uint
, orulong
, 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 tipoulong
, desde que o valor da constant_expression não seja negativo.A constant_expression of typelong
can be converted to typeulong
, 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 efetivaC
, deT
para qualquer classe base deC
, e deT
para qualquer interface implementada peloC
.FromT
to its effective base classC
, fromT
to any base class ofC
, and fromT
to any interface implemented byC
. Em tempo de execução, seT
for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, ifT
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 interfaceI
noT
conjunto de interfaces efetivas e deT
para qualquer interface base doI
.FromT
to an interface typeI
inT
's effective interface set and fromT
to any base interface ofI
. Em tempo de execução, seT
for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, ifT
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 tipoU
, fornecidoT
depende deU
(restrições de parâmetro detipo).FromT
to a type parameterU
, providedT
depends onU
(Type parameter constraints). Em tempo de execução, seU
for um tipo de valor, será,T
U
necessariamente, o mesmo tipo e nenhuma conversão será executada.At run-time, ifU
is a value type, thenT
andU
are necessarily the same type and no conversion is performed. Caso contrário, seT
for um tipo de valor, a conversão será executada como uma conversão boxing.Otherwise, ifT
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
, fornecidoT
é conhecido como um tipo de referência.From the null literal toT
, providedT
is known to be a reference type. - De
T
para um tipo de referênciaI
se ele tiver uma conversão implícita para um tipo de referênciaS0
eS0
tiver uma conversão de identidade paraS
.FromT
to a reference typeI
if it has an implicit conversion to a reference typeS0
andS0
has an identity conversion toS
. Em tempo de execução, a conversão é executada da mesma maneira que a conversão paraS0
.At run-time the conversion is executed the same way as the conversion toS0
. - De
T
para um tipo de interfaceI
se ele tem uma conversão implícita para uma interface ou tipo delegadoI0
eI0
é convertido em variância paraI
(conversão devariância).FromT
to an interface typeI
if it has an implicit conversion to an interface or delegate typeI0
andI0
is variance-convertible toI
(Variance conversion). Em tempo de execução, seT
for um tipo de valor, a conversão será executada como uma conversão boxing.At run-time, ifT
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
parabyte
,ushort
,uint
,ulong
ouchar
.Fromsbyte
tobyte
,ushort
,uint
,ulong
, orchar
. - De
byte
parasbyte
echar
.Frombyte
tosbyte
andchar
. - De
short
parasbyte
,byte
,ushort
,uint
,ulong
ouchar
.Fromshort
tosbyte
,byte
,ushort
,uint
,ulong
, orchar
. - Do
ushort
parasbyte
,byte
,short
ouchar
.Fromushort
tosbyte
,byte
,short
, orchar
. - De
int
parasbyte
,,,,,byte
short
ushort
uint
ulong
ouchar
.Fromint
tosbyte
,byte
,short
,ushort
,uint
,ulong
, orchar
. - De
uint
parasbyte
,byte
,short
,ushort
,int
ouchar
.Fromuint
tosbyte
,byte
,short
,ushort
,int
, orchar
. - De
long
parasbyte
,byte
,,,,,short
ushort
int
uint
ulong
ouchar
.Fromlong
tosbyte
,byte
,short
,ushort
,int
,uint
,ulong
, orchar
. - De
ulong
parasbyte
,byte
,,,,,short
ushort
int
uint
long
ouchar
.Fromulong
tosbyte
,byte
,short
,ushort
,int
,uint
,long
, orchar
. - Do
char
parasbyte
,byte
oushort
.Fromchar
tosbyte
,byte
, orshort
. - De
float
parasbyte
,byte
,,,,,short
ushort
int
uint
long
,ulong
,char
oudecimal
.Fromfloat
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
, ordecimal
. - De
double
parasbyte
,byte
,,,,,short
ushort
int
uint
long
,ulong
,char
,float
oudecimal
.Fromdouble
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
, ordecimal
. - De
decimal
parasbyte
,byte
,,,,,short
ushort
int
uint
long
,ulong
,char
,float
oudouble
.Fromdecimal
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
, ordouble
.
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á umSystem.OverflowException
se o valor do operando de origem estiver fora do intervalo do tipo de destino.In achecked
context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws aSystem.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 anunchecked
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.
- Em um
- 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 fromdecimal
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, umSystem.OverflowException
será lançado.If the resulting integral value is outside the range of the destination type, aSystem.OverflowException
is thrown. - Para uma conversão de
float
oudouble
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 fromfloat
ordouble
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 achecked
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, aSystem.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, aSystem.OverflowException
is thrown.
- Se o valor do operando for NaN ou infinito, um
- Em um
unchecked
contexto, a conversão sempre é bem sucedido e prossegue da seguinte maneira.In anunchecked
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.
- Em um
- Para uma conversão de
double
parafloat
, odouble
valor é arredondado para o valor mais próximofloat
.For a conversion fromdouble
tofloat
, thedouble
value is rounded to the nearestfloat
value. Se odouble
valor for muito pequeno para representar como umfloat
, o resultado se tornará positivo zero ou negativo zero.If thedouble
value is too small to represent as afloat
, the result becomes positive zero or negative zero. Se odouble
valor for muito grande para representar como umfloat
, o resultado se tornará infinito positivo ou infinito negativo.If thedouble
value is too large to represent as afloat
, the result becomes positive infinity or negative infinity. Se odouble
valor for NaN, o resultado também será Nan.If thedouble
value is NaN, the result is also NaN. - Para uma conversão de
float
oudouble
paradecimal
, o valor de origem é convertido emdecimal
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 fromfloat
ordouble
todecimal
, the source value is converted todecimal
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 umdecimal
, o resultado se tornará zero.If the source value is too small to represent as adecimal
, the result becomes zero. Se o valor de Source for NaN, Infinity ou muito grande para representar como umdecimal
, umSystem.OverflowException
será lançado.If the source value is NaN, infinity, or too large to represent as adecimal
, aSystem.OverflowException
is thrown. - Para uma conversão de
decimal
parafloat
oudouble
, odecimal
valor é arredondado para o valor mais próximodouble
oufloat
.For a conversion fromdecimal
tofloat
ordouble
, thedecimal
value is rounded to the nearestdouble
orfloat
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
oudecimal
para qualquer enum_type.Fromsbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
, ordecimal
to any enum_type. - De qualquer enum_type para,,,,,,,
sbyte
byte
short
ushort
int
uint
long
ulong
,char
,float
,double
oudecimal
.From any enum_type tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
, ordecimal
. - 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?
paraT?
.An explicit conversion fromS?
toT?
. - Uma conversão explícita de
S
paraT?
.An explicit conversion fromS
toT?
. - Uma conversão explícita de
S?
paraT
.An explicit conversion fromS?
toT
.
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?
paraT?
:If the nullable conversion is fromS?
toT?
:- Se o valor de origem for NULL (a
HasValue
propriedade é false), o resultado será o valor nulo do tipoT?
.If the source value is null (HasValue
property is false), the result is the null value of typeT?
. - Caso contrário, a conversão é avaliada como um desempacotamento de
S?
paraS
, seguida pela conversão subjacente deS
paraT
, seguida de um encapsulamento deT
paraT?
.Otherwise, the conversion is evaluated as an unwrapping fromS?
toS
, followed by the underlying conversion fromS
toT
, followed by a wrapping fromT
toT?
.
- Se o valor de origem for NULL (a
- Se a conversão anulável for de
S
paraT?
, a conversão será avaliada como a conversão subjacente deS
paraT
seguida de um encapsulamento deT
paraT?
.If the nullable conversion is fromS
toT?
, the conversion is evaluated as the underlying conversion fromS
toT
followed by a wrapping fromT
toT?
. - Se a conversão anulável for de
S?
paraT
, a conversão será avaliada como um desempacotamento deS?
paraS
seguido pela conversão subjacente deS
paraT
.If the nullable conversion is fromS?
toT
, the conversion is evaluated as an unwrapping fromS?
toS
followed by the underlying conversion fromS
toT
.
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
edynamic
para qualquer outro reference_type.Fromobject
anddynamic
to any other reference_type. - De qualquer class_type
S
a qualquer class_typeT
, fornecidoS
é uma classe base deT
.From any class_typeS
to any class_typeT
, providedS
is a base class ofT
. - De qualquer class_type
S
a qualquer interface_typeT
, fornecidoS
não é lacrado e fornecido nãoS
implementaT
.From any class_typeS
to any interface_typeT
, providedS
is not sealed and providedS
does not implementT
. - De qualquer interface_type
S
a qualquer class_typeT
, fornecidaT
não é uma implementação selada ou fornecidaT
S
.From any interface_typeS
to any class_typeT
, providedT
is not sealed or providedT
implementsS
. - De qualquer interface_type
S
a qualquer interface_typeT
, fornecidoS
não é derivado deT
.From any interface_typeS
to any interface_typeT
, providedS
is not derived fromT
. - De um array_type
S
com um tipo de elementoSE
para um array_typeT
com um tipo de elementoTE
, desde que todas as seguintes opções sejam verdadeiras:From an array_typeS
with an element typeSE
to an array_typeT
with an element typeTE
, provided all of the following are true:S
eT
difere somente no tipo de elemento.S
andT
differ only in element type. Em outras palavras,S
eT
têm o mesmo número de dimensões.In other words,S
andT
have the same number of dimensions.- Ambos
SE
eTE
são reference_type s.BothSE
andTE
are reference_type s. - Existe uma conversão de referência explícita de
SE
paraTE
.An explicit reference conversion exists fromSE
toTE
.
System.Array
E as interfaces que ele implementa para qualquer array_type.FromSystem.Array
and the interfaces it implements to any array_type.- De um tipo de matriz unidimensional
S[]
paraSystem.Collections.Generic.IList<T>
o e suas interfaces base, desde que haja uma conversão de referência explícita deS
paraT
.From a single-dimensional array typeS[]
toSystem.Collections.Generic.IList<T>
and its base interfaces, provided that there is an explicit reference conversion fromS
toT
. - De
System.Collections.Generic.IList<S>
e suas interfaces base para um tipo de matriz unidimensionalT[]
, desde que haja uma conversão explícita de identidade ou referência deS
paraT
.FromSystem.Collections.Generic.IList<S>
and its base interfaces to a single-dimensional array typeT[]
, provided that there is an explicit identity or reference conversion fromS
toT
. System.Delegate
E as interfaces que ele implementa para qualquer delegate_type.FromSystem.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ênciaT0
eT0
tiver uma conversão de identidadeT
.From a reference type to a reference typeT
if it has an explicit reference conversion to a reference typeT0
andT0
has an identity conversionT
. - 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 delegadoT0
eT0
for conversível em variânciaT
ou seT
for convertido em variância paraT0
(conversão devariância).From a reference type to an interface or delegate typeT
if it has an explicit reference conversion to an interface or delegate typeT0
and eitherT0
is variance-convertible toT
orT
is variance-convertible toT0
(Variance conversion). - De
D<S1...Sn>
paraD<T1...Tn>
ondeD<X1...Xn>
é um tipo de delegado genérico,D<S1...Sn>
não é compatível com or idêntico aD<T1...Tn>
e para cada parâmetroXi
de tipo dasD
seguintes isenções:FromD<S1...Sn>
toD<T1...Tn>
whereD<X1...Xn>
is a generic delegate type,D<S1...Sn>
is not compatible with or identical toD<T1...Tn>
, and for each type parameterXi
ofD
the following holds:- Se
Xi
for invariável,Si
será idêntico aTi
.IfXi
is invariant, thenSi
is identical toTi
. - Se
Xi
for covariant, haverá uma identidade implícita ou explícita ou conversão de referência deSi
paraTi
.IfXi
is covariant, then there is an implicit or explicit identity or reference conversion fromSi
toTi
. - Se
Xi
for contravariant, entãoSi
seráTi
idêntico ou ambos os tipos de referência.IfXi
is contravariant, thenSi
andTi
are either identical or both reference types.
- Se
- 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
deT
paraT
e de qualquer classe base deC
paraT
.From the effective base classC
ofT
toT
and from any base class ofC
toT
. Em tempo de execução, seT
for um tipo de valor, a conversão será executada como uma conversão não boxing.At run-time, ifT
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 toT
. Em tempo de execução, seT
for um tipo de valor, a conversão será executada como uma conversão não boxing.At run-time, ifT
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_typeI
fornecido, ainda não há uma conversão implícita deT
paraI
.FromT
to any interface_typeI
provided there is not already an implicit conversion fromT
toI
. Em tempo de execução, seT
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, ifT
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
paraT
, fornecidoT
depende deU
(restrições de parâmetro detipo).From a type parameterU
toT
, providedT
depends onU
(Type parameter constraints). Em tempo de execução, seU
for um tipo de valor, será,T
U
necessariamente, o mesmo tipo e nenhuma conversão será executada.At run-time, ifU
is a value type, thenT
andU
are necessarily the same type and no conversion is performed. Caso contrário, seT
for um tipo de valor, a conversão será executada como uma conversão não boxing.Otherwise, ifT
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:
- Conversões de identidade (conversão de identidade)Identity conversions (Identity conversion)
- Conversões numéricas implícitas (conversões numéricas implícitas)Implicit numeric conversions (Implicit numeric conversions)
- Conversões anuláveis implícitas (conversões anuláveis implícitas)Implicit nullable conversions (Implicit nullable conversions)
- Conversões implícitas de referência (conversões de referência implícitas)Implicit reference conversions (Implicit reference conversions)
- Conversões Boxing (conversões Boxing)Boxing conversions (Boxing conversions)
- Conversões de expressão de constante implícita (conversões de expressão de constante implícita)Implicit constant expression conversions (Implicit constant expression conversions)
- Conversões implícitas envolvendo parâmetros de tipo (conversões implícitas envolvendo parâmetros de tipo)Implicit conversions involving type parameters (Implicit conversions involving type parameters)
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
eT0
são tipos diferentes.S0
andT0
are different types.S0
OuT0
é o tipo de classe ou struct no qual a declaração do operador ocorre.EitherS0
orT0
is the class or struct type in which the operator declaration takes place.- Nem
S0
nemT0
é um interface_type.NeitherS0
norT0
is an interface_type. - Excluindo conversões definidas pelo usuário, uma conversão não existe de
S
ou paraT
T
S
.Excluding user-defined conversions, a conversion does not exist fromS
toT
or fromT
toS
.
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 tipoB
, e se nemA
B
for interface_type s,A
será dito que é * englobado por _B
eB
é dito como _ ** *A
.If a standard implicit conversion (Standard implicit conversions) exists from a typeA
to a typeB
, and if neitherA
norB
are interface_type s, thenA
is said to be encompassed by _B
, andB
is said to _ encompassA
. - 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
eT0
.Determine the typesS0
andT0
. IfS
ouT
são tipos anuláveis,S0
eT0
são seus tipos subjacentes, caso contrário,S0
eT0
são iguais aS
eT
respectivamente.IfS
orT
are nullable types,S0
andT0
are their underlying types, otherwiseS0
andT0
are equal toS
andT
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 emS0
(ifS0
é uma classe ou struct), as classes base deS0
(ifS0
é uma classe) eT0
(ifT0
é uma Class ou struct).This set consists ofS0
(ifS0
is a class or struct), the base classes ofS0
(ifS0
is a class), andT0
(ifT0
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 noD
que são convertidas de um tipo que abrangeS
um tipo que é abrangedo porT
.This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs inD
that convert from a type encompassingS
to a type encompassed byT
. SeU
estiver vazio, a conversão será indefinida e ocorrerá um erro de tempo de compilação.IfU
is empty, the conversion is undefined and a compile-time error occurs. - Localize o tipo de fonte mais específico,
SX
, dos operadores emU
:Find the most specific source type,SX
, of the operators inU
:- Se qualquer um dos operadores em
U
converter deS
,SX
forS
.If any of the operators inU
convert fromS
, thenSX
isS
. - Caso contrário,
SX
é o tipo mais abrangente no conjunto combinado de tipos de origem dos operadores noU
.Otherwise,SX
is the most encompassed type in the combined set of source types of the operators inU
. 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.
- Se qualquer um dos operadores em
- Localize o tipo de destino mais específico,
TX
, dos operadores emU
:Find the most specific target type,TX
, of the operators inU
:- Se qualquer um dos operadores em
U
converter paraT
,TX
forT
.If any of the operators inU
convert toT
, thenTX
isT
. - Caso contrário,
TX
é o tipo mais abrangente no conjunto combinado de tipos de destino dos operadores noU
.Otherwise,TX
is the most encompassing type in the combined set of target types of the operators inU
. 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.
- Se qualquer um dos operadores em
- 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 deSX
paraTX
, esse será o operador de conversão mais específico.IfU
contains exactly one user-defined conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator. - Caso contrário, se
U
contiver exatamente um operador de conversão levantado que converta deSX
paraTX
, esse será o operador de conversão mais específico.Otherwise, ifU
contains exactly one lifted conversion operator that converts fromSX
toTX
, 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.
- Se
- Por fim, aplique a conversão:Finally, apply the conversion:
- Se
S
não forSX
, uma conversão implícita padrão deS
paraSX
será executada.IfS
is notSX
, then a standard implicit conversion fromS
toSX
is performed. - O operador de conversão mais específico é chamado para converter de
SX
paraTX
.The most specific conversion operator is invoked to convert fromSX
toTX
. - Se
TX
não forT
, uma conversão implícita padrão deTX
paraT
será executada.IfTX
is notT
, then a standard implicit conversion fromTX
toT
is performed.
- Se
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
eT0
.Determine the typesS0
andT0
. IfS
ouT
são tipos anuláveis,S0
eT0
são seus tipos subjacentes, caso contrário,S0
eT0
são iguais aS
eT
respectivamente.IfS
orT
are nullable types,S0
andT0
are their underlying types, otherwiseS0
andT0
are equal toS
andT
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 emS0
(seS0
for uma classe ou struct), as classes base deS0
(seS0
for uma classe),T0
(seT0
for uma classe ou estrutura) e as classes base deT0
(seT0
for uma classe).This set consists ofS0
(ifS0
is a class or struct), the base classes ofS0
(ifS0
is a class),T0
(ifT0
is a class or struct), and the base classes ofT0
(ifT0
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 noD
que são convertidos de um tipo que abrange ou é derivado deS
para um tipo que abrange ou abrangedo peloT
.This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs inD
that convert from a type encompassing or encompassed byS
to a type encompassing or encompassed byT
. SeU
estiver vazio, a conversão será indefinida e ocorrerá um erro de tempo de compilação.IfU
is empty, the conversion is undefined and a compile-time error occurs. - Localize o tipo de fonte mais específico,
SX
, dos operadores emU
:Find the most specific source type,SX
, of the operators inU
:- Se qualquer um dos operadores em
U
converter deS
,SX
forS
.If any of the operators inU
convert fromS
, thenSX
isS
. - Caso contrário, se qualquer um dos operadores em
U
converter dos tipos que englobamS
,SX
será o tipo mais abrangedo no conjunto combinado de tipos de origem desses operadores.Otherwise, if any of the operators inU
convert from types that encompassS
, thenSX
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 noU
.Otherwise,SX
is the most encompassing type in the combined set of source types of the operators inU
. 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.
- Se qualquer um dos operadores em
- Localize o tipo de destino mais específico,
TX
, dos operadores emU
:Find the most specific target type,TX
, of the operators inU
:- Se qualquer um dos operadores em
U
converter paraT
,TX
forT
.If any of the operators inU
convert toT
, thenTX
isT
. - Caso contrário, se qualquer um dos operadores em
U
converter para tipos que são incluídos peloT
,TX
será o tipo mais abrangente no conjunto combinado de tipos de destino desses operadores.Otherwise, if any of the operators inU
convert to types that are encompassed byT
, thenTX
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 noU
.Otherwise,TX
is the most encompassed type in the combined set of target types of the operators inU
. 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.
- Se qualquer um dos operadores em
- 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 deSX
paraTX
, esse será o operador de conversão mais específico.IfU
contains exactly one user-defined conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator. - Caso contrário, se
U
contiver exatamente um operador de conversão levantado que converta deSX
paraTX
, esse será o operador de conversão mais específico.Otherwise, ifU
contains exactly one lifted conversion operator that converts fromSX
toTX
, 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.
- Se
- Por fim, aplique a conversão:Finally, apply the conversion:
- Se
S
não forSX
, uma conversão explícita padrão deS
paraSX
será executada.IfS
is notSX
, then a standard explicit conversion fromS
toSX
is performed. - O operador de conversão mais específico definido pelo usuário é chamado para converter de
SX
paraTX
.The most specific user-defined conversion operator is invoked to convert fromSX
toTX
. - Se
TX
não forT
, uma conversão explícita padrão deTX
paraT
será executada.IfTX
is notT
, then a standard explicit conversion fromTX
toT
is performed.
- Se
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
eF
terá o mesmo número de parâmetros.IfF
contains an anonymous_function_signature, thenD
andF
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 deD
tenha oout
modificador de parâmetro.IfF
does not contain an anonymous_function_signature, thenD
may have zero or more parameters of any type, as long as no parameter ofD
has theout
parameter modifier. - Se o
F
tiver uma lista de parâmetros tipados explicitamente, cada parâmetro noD
terá o mesmo tipo e modificadores que o parâmetro correspondente noF
.IfF
has an explicitly typed parameter list, each parameter inD
has the same type and modifiers as the corresponding parameter inF
. - Se
F
o tiver uma lista de parâmetros Tipados implicitamente, oD
não teráref
out
parâmetros ou.IfF
has an implicitly typed parameter list,D
has noref
orout
parameters. - Se o corpo de
F
for uma expressão eD
tiver um tipo devoid
retorno ouF
for Async eD
tiver o tipo de retornoTask
, quando cada parâmetro deF
for dado o tipo do parâmetro correspondente noD
, o corpo deF
será uma expressão válida (wrt Expressions) que seria permitida como uma statement_expression (instruções de expressão).If the body ofF
is an expression, and eitherD
has avoid
return type orF
is async andD
has the return typeTask
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
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 eD
tiver umvoid
tipo de retorno ouF
for Async eD
tiver o tipo de retornoTask
, quando cada parâmetro deF
for dado o tipo do parâmetro correspondente noD
, o corpo deF
será um bloco de instrução válido ( blocosWRT) em que nenhumareturn
instrução especifica uma expressão.If the body ofF
is a statement block, and eitherD
has avoid
return type orF
is async andD
has the return typeTask
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid statement block (wrt Blocks) in which noreturn
statement specifies an expression. - Se o corpo de
F
for uma expressão, eF
for não Async eD
tiver um tipo de retorno não voidT
, ouF
for Async eD
tiver um tipo de retornoTask<T>
, quando cada parâmetro deF
for dado o tipo do parâmetro correspondente noD
, o corpo deF
será uma expressão válida (WRT Expressions) que é implicitamente conversível paraT
.If the body ofF
is an expression, and eitherF
is non-async andD
has a non-void return typeT
, orF
is async andD
has a return typeTask<T>
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid expression (wrt Expressions) that is implicitly convertible toT
. - Se o corpo de
F
for um bloco de instrução, eF
é não Async eD
tem um tipo de retorno não voidT
, ouF
é Async eD
tem um tipo de retornoTask<T>
, quando cada parâmetro deF
recebe o tipo do parâmetro correspondente noD
, o corpo deF
é um bloco de instrução válido ( blocosWRT) com um ponto de extremidade não acessível no qual cadareturn
instrução especifica uma expressão que é implicitamente conversível paraT
.If the body ofF
is a statement block, and eitherF
is non-async andD
has a non-void return typeT
, orF
is async andD
has a return typeTask<T>
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid statement block (wrt Blocks) with a non-reachable end point in which eachreturn
statement specifies an expression that is implicitly convertible toT
.
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árioE(A)
, com as seguintes modificações:A single methodM
is selected corresponding to a method invocation (Method invocations) of the formE(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
ouout
) do parâmetro correspondente no formal_parameter_list deD
.The argument listA
is a list of expressions, each classified as a variable and with the type and modifier (ref
orout
) of the corresponding parameter in the formal_parameter_list ofD
. - 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.
- A lista
- 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 queD
e a conversão é considerada como existente.Otherwise the algorithm produces a single best methodM
having the same number of parameters asD
and the conversion is considered to exist. - O método selecionado
M
deve ser compatível (delegar compatibilidade) com o tipo delegadoD
ou, caso contrário, ocorrerá um erro de tempo de compilação.The selected methodM
must be compatible (Delegate compatibility) with the delegate typeD
, 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 aE
determinará o objeto de destino do delegado.If the selected methodM
is an instance method, the instance expression associated withE
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 typeD
, 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 ofE(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 withE
:- 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
, umSystem.NullReferenceException
será lançado e nenhuma etapa adicional será executada.If the selected method is an instance method and the target object isnull
, aSystem.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 isnull
. - Uma nova instância do tipo delegado
D
é alocada.A new instance of the delegate typeD
is allocated. Se não houver memória suficiente disponível para alocar a nova instância, umSystem.OutOfMemoryException
será lançado e nenhuma etapa adicional será executada.If there is not enough memory available to allocate the new instance, aSystem.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.