Elenco e conversões (F#)
Este tópico descreve o suporte para conversões de tipo em F#.
Tipos de aritméticos
F# fornece os operadores de conversão para conversões aritméticas entre vários tipos primitivos, como entre inteiro e tipos de ponto flutuante. Os operadores de conversão integral e char verificou e formulários desmarcados; Operadores de ponto do flutuante e o enum o operador de conversão do não. Os formulários não verificados são definidos em Microsoft.FSharp.Core.Operators e os formulários selecionados são definidos em Microsoft.FSharp.Core.Operators.Checked. Os formulários selecionados de excedentes e geram uma exceção de tempo de execução se o valor resultante exceder os limites do tipo de destino.
Cada um desses operadores tem o mesmo nome que o nome do tipo de destino. Por exemplo, no código a seguir, na qual os tipos explicitamente são anotados, byte aparece com dois significados diferentes. A primeira ocorrência é o tipo e o segundo é o operador de conversão.
let x : int = 5
let b : byte = byte x
A tabela a seguir mostra os operadores de conversão definidos em F#.
Operador |
Descrição |
---|---|
byte |
Converta em bytes, um tipo não assinado de 8 bits. |
sbyte |
Converta em byte assinado. |
int16 |
Converta um inteiro assinado de 16 bits. |
uint16 |
Converta um inteiro não assinado de 16 bits. |
int32, int |
Converta um inteiro assinado de 32 bits. |
uint32 |
Converta um inteiro não assinado de 32 bits. |
int64 |
Converta um inteiro assinado de 64 bits. |
uint64 |
Converta um inteiro não assinado de 64 bits. |
nativeint |
Converta um inteiro nativo. |
unativeint |
Converta para um inteiro não assinado de nativo. |
float, double |
Converta um IEEE de precisão dupla de 64 bits número de ponto flutuante. |
float32, single |
Converta um IEEE de precisão simples de 32 bits que número de ponto flutuante. |
decimal |
Converter em System.Decimal. |
char |
Converter em System.Char, um caractere Unicode. |
enum |
Converta um tipo enumerado. |
Além de para tipos primitivos internos, você pode usar esses operadores com tipos que implementam op_Explicit ou op_Implicit métodos com assinaturas apropriado. Por exemplo, o int o operador de conversão funciona com qualquer tipo que fornece um método estático op_Explicit que leva o tipo como um parâmetro e retorna int. Como uma exceção especial para a regra geral que os métodos não podem ser sobrecarregados pelo tipo de retorno, você pode fazer isso para op_Explicit e op_Implicit.
Tipos enumerados
O enum operador é um operador genérico que leva um parâmetro de tipo que representa o tipo da enum para converter para. Quando o converte para um tipo enumerado, digite inferência tenta determinar o tipo da enum que você deseja converter. No exemplo a seguir, a variável col1 não for anotado explicitamente, mas seu tipo é inferido do Test de igualdade posterior. Portanto, o compilador pode deduzir que você estiver convertendo para uma Color enumeração. Como alternativa, você pode fornecer uma anotação de tipo, como com col2 o exemplo a seguir.
type Color =
| Red = 1
| Green = 2
| Blue = 3
// The target type of the conversion is determined by type inference.
let col1 = enum 1
// The target type is supplied by a type annotation.
let col2 : Color = enum 2
do
if (col1 = Color.Red) then
printfn "Red"
A projeção de tipos de objeto
A conversão entre tipos em uma hierarquia de objetos é fundamental para programação orientada a objeto. Há dois tipos básicos de conversões: a projeção (upcasting) e a projeção para baixo (Baixar). Conversão de uma hierarquia significa a projeção de uma referência de objeto derivado a uma referência de objeto base. Uma conversão é garantida para funcionar como a classe base é na hierarquia de herança da classe derivada. Projetando uma hierarquia de uma referência de objeto de base para uma referência de objeto derivado terá êxito somente se o objeto, na verdade, é uma instância do tipo correto de destino (derivado) ou um tipo derivado do tipo de destino.
F# fornece a operadores para esses tipos de conversões. O :> operador projeta na hierarquia e o :?> operador projeta para baixo da hierarquia.
Upcasting
Em muitas linguagens orientadas a objeto, o upcasting é implícito; no F#, as regras são ligeiramente diferentes. Upcasting é aplicado automaticamente quando você passar argumentos para métodos em um tipo de objeto. No entanto, para funções de let vinculados em um módulo, upcasting não é automática, a menos que o tipo de parâmetro é declarado como um tipo flexível. Para obter mais informações, consulte Tipos flexíveis (F#).
O :> operador executa uma conversão estática, que significa que o sucesso do tom é determinado em tempo de compilação. Se uma conversão que usa :> compilado com êxito, ele é uma conversão válida e não possui nenhuma chance de falhas em tempo de execução.
Você também pode usar o upcast o operador para executar tal uma conversão. A expressão a seguir especifica uma conversão da hierarquia.
upcast expression
Quando você usa o operador elevado, o compilador tenta inferir o tipo que você está convertendo a partir do contexto. Se o compilador não pode determinar o tipo de destino, o compilador reporta um erro.
Baixar
O :?> operador executa uma conversão dinâmica, que significa que o sucesso do tom é determinado em tempo de execução. Uma conversão que usa o :?> operador não estiver marcada em tempo de compilação; mas, em tempo de execução é feita uma tentativa para converter para o tipo especificado. Se o objeto for compatível com o tipo de destino, a projeção é bem-sucedida. Se o objeto não é compatível com o tipo de destino, o tempo de execução gera um InvalidCastException.
Você também pode usar o downcast operador para executar uma conversão de tipo dinâmico. A expressão a seguir especifica uma conversão para baixo na hierarquia para um tipo que é inferido a partir do contexto do programa.
downcast expression
Para o operador elevado, se o compilador não é possível inferir um tipo de destino específico do contexto, ele reporta um erro.
O código a seguir ilustra o uso de :> e :?> operadores. O código ilustra que o :?> é melhor usado quando você conhece a conversão seja bem-sucedida, pois ele lança InvalidCastException se a falha de conversão. Se você não souber que uma conversão seja bem-sucedida, um teste de tipo que usa um match a expressão é melhor porque evita a sobrecarga de gerar uma exceção.
type Base1() =
abstract member F : unit -> unit
default u.F() =
printfn "F Base1"
type Derived1() =
inherit Base1()
override u.F() =
printfn "F Derived1"
let d1 : Derived1 = Derived1()
// Upcast to Base1.
let base1 = d1 :> Base1
// This might throw an exception, unless
// you are sure that base1 is really a Derived1 object, as
// is the case here.
let derived1 = base1 :?> Derived1
// If you cannot be sure that b1 is a Derived1 object,
// use a type test, as follows:
let downcastBase1 (b1 : Base1) =
match b1 with
| :? Derived1 as derived1 -> derived1.F()
| _ -> ()
downcastBase1 base1
Porque os operadores genéricos downcast e upcast dependem de inferência de tipo para determinar o tipo de argumento e o retorno no código acima, você pode substituir
let base1 = d1 :> Base1
com
base1 = upcast d1
No código anterior, o tipo de argumento e os tipos de retorno são Derived1 e Base1, respectivamente.
Para obter mais informações sobre testes de tipo, consulte Corresponder expressões (F#).
Consulte também
Outros recursos
Histórico de alterações
Date |
History |
Motivo |
---|---|---|
Setembro de 2010 |
Adicionadas informações sobre a sobrecarga op_Explicit e op_Implicit retornar tipo. |
Aprimoramento de informações. |