Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan dukungan untuk konversi jenis di F#.
Jenis Aritmatika
F# menyediakan operator konversi untuk konversi aritmatika antara berbagai jenis primitif, seperti antara jenis bilangan bulat dan titik pecahan. Operator konversi integral dan karakter telah memeriksa dan menghapus centang formulir; operator titik mengambang dan enum operator konversi tidak. Formulir yang tidak dicentang didefinisikan di FSharp.Core.Operators dan formulir yang dicentang ditentukan dalam FSharp.Core.Operators.Checked. Formulir yang dicentang memeriksa luapan dan menghasilkan pengecualian runtime jika nilai yang dihasilkan melebihi batas jenis target.
Masing-masing operator ini memiliki nama yang sama dengan nama jenis tujuan. Misalnya, dalam kode berikut, di mana jenis secara eksplisit dianotasikan, byte muncul dengan dua arti yang berbeda. Kemunculan pertama adalah jenis dan yang kedua adalah operator konversi.
let x : int = 5
let b : byte = byte x
Tabel berikut menunjukkan operator konversi yang ditentukan dalam F#.
| Pengoperasi | Deskripsi |
|---|---|
byte |
Konversi ke byte, jenis tidak ditandatangani 8-bit. |
sbyte |
Konversi ke byte yang ditandatangani. |
int16 |
Konversi ke bilangan bulat bertanda tangan 16-bit. |
uint16 |
Konversi ke bilangan bulat yang tidak ditandatangani 16-bit. |
int32, int |
Konversi ke bilangan bulat bertanda tangan 32-bit. |
uint32 |
Konversi ke bilangan bulat yang tidak ditandatangani 32-bit. |
int64 |
Konversi ke bilangan bulat bertanda tangan 64-bit. |
uint64 |
Konversi ke bilangan bulat yang tidak ditandatangani 64-bit. |
nativeint |
Konversi ke bilangan bulat asli. |
unativeint |
Konversi ke bilangan bulat asli yang tidak ditandatangani. |
float, double |
Konversikan ke angka titik mengambang IEEE presisi ganda 64-bit. |
float32, single |
Konversi ke angka titik mengambang IEEE presisi tunggal 32-bit. |
decimal |
Konversi ke System.Decimal. |
char |
Konversi ke System.Char, karakter Unicode. |
enum |
Konversi ke jenis enumerasi. |
Selain jenis primitif bawaan, Anda dapat menggunakan operator ini dengan jenis yang mengimplementasikan op_Explicit atau op_Implicit metode dengan tanda tangan yang sesuai. Misalnya, int operator konversi bekerja dengan jenis apa pun yang menyediakan metode op_Explicit statis yang mengambil jenis sebagai parameter dan mengembalikan int. Sebagai pengecualian khusus untuk aturan umum bahwa metode tidak dapat kelebihan beban berdasarkan jenis pengembalian, Anda dapat melakukan ini untuk op_Explicit dan op_Implicit.
Jenis Enumerasi
Operator enum adalah operator generik yang mengambil satu parameter jenis yang mewakili jenis yang akan dikonversi enum . Saat dikonversi ke jenis enumerasi, ketik inferensi mencoba menentukan jenis enum yang ingin Anda konversi. Dalam contoh berikut, variabel col1 tidak secara eksplisit dianotasikan, tetapi jenisnya disimpulkan dari pengujian kesetaraan yang lebih baru. Oleh karena itu, kompilator dapat menyimpulkan bahwa Anda mengonversi ke Color enumerasi. Atau, Anda dapat menyediakan anotasi jenis, seperti col2 dalam contoh berikut.
type Color =
| Red = 1
| Green = 2
| Blue = 3
// The target type of the conversion cannot be determined by type inference, so the type parameter must be explicit.
let col1 = enum<Color> 1
// The target type is supplied by a type annotation.
let col2 : Color = enum 2
Anda juga dapat menentukan jenis enumerasi target secara eksplisit sebagai parameter jenis, seperti dalam kode berikut:
let col3 = enum<Color> 3
Perhatikan bahwa enumerasi yang ditransmisikan hanya berfungsi jika jenis enumerasi yang mendasar kompatibel dengan jenis yang sedang dikonversi. Dalam kode berikut, konversi gagal dikompilasi karena ketidakcocokan antara int32 dan uint32.
// Error: types are incompatible
let col4 : Color = enum 2u
Untuk informasi selengkapnya, lihat Enumerasi.
Jenis Objek Casting
Konversi antara jenis dalam hierarki objek sangat mendasar untuk pemrograman berorientasi objek. Ada dua jenis konversi dasar: casting up (upcasting) dan casting down (downcasting). Mentransmisikan hierarki berarti transmisi dari referensi objek turunan ke referensi objek dasar. Pemeran semacam itu dijamin berfungsi selama kelas dasar berada dalam hierarki warisan kelas turunan. Mentransmisikan hierarki, dari referensi objek dasar ke referensi objek turunan, hanya berhasil jika objek sebenarnya adalah instans jenis tujuan (turunan) yang benar atau jenis yang berasal dari jenis tujuan.
F# menyediakan operator untuk jenis konversi ini. Operator :> mentransmisikan hierarki, dan :?> operator mentransmisikan hierarki.
Upcasting
Dalam banyak bahasa berorientasi objek, upcasting bersifat implisit; di F#, aturannya sedikit berbeda. Upcasting diterapkan secara otomatis saat Anda meneruskan argumen ke metode pada jenis objek. Namun, untuk fungsi let-bound dalam modul, upcasting tidak otomatis, kecuali jenis parameter dinyatakan sebagai jenis fleksibel. Untuk informasi selengkapnya, lihat Jenis Fleksibel.
Operator :> melakukan pemeran statis, yang berarti bahwa keberhasilan pemeran ditentukan pada waktu kompilasi. Jika cast yang berhasil menggunakan :> kompilasi, itu adalah cast yang valid dan tidak memiliki kemungkinan kegagalan pada run time.
Anda juga dapat menggunakan upcast operator untuk melakukan konversi tersebut. Ekspresi berikut menentukan konversi hierarki:
upcast expression
Saat Anda menggunakan operator upcast, pengkompilasi mencoba menyimpulkan jenis yang Anda konversi dari konteks. Jika pengkompilasi tidak dapat menentukan jenis target, pengkompilasi melaporkan kesalahan. Anotasi jenis mungkin diperlukan.
Konversi Tipe Ke Turunan (Downcasting)
Operator :?> melakukan pemeran dinamis, yang berarti bahwa keberhasilan pemeran ditentukan pada waktu proses. Transmisi yang menggunakan :?> operator tidak diperiksa pada waktu kompilasi; tetapi pada waktu proses, upaya dilakukan untuk mentransmisikan ke jenis yang ditentukan. Jika objek kompatibel dengan jenis target, pemeran berhasil. Jika objek tidak kompatibel dengan jenis target, runtime akan menaikkan InvalidCastException.
Anda juga dapat menggunakan downcast operator untuk melakukan konversi jenis dinamis. Ekspresi berikut menentukan konversi hierarki ke jenis yang disimpulkan dari konteks program:
downcast expression
Adapun upcast operator, jika pengkompilasi tidak dapat menyimpulkan jenis target tertentu dari konteks, ia melaporkan kesalahan. Anotasi jenis mungkin diperlukan.
Kode berikut mengilustrasikan penggunaan :> operator dan :?> . Kode ini menggambarkan bahwa :?> operator paling baik digunakan ketika Anda tahu bahwa konversi akan berhasil, karena melemparkan InvalidCastException jika konversi gagal. Jika Anda tidak tahu bahwa konversi akan berhasil, pengujian jenis yang menggunakan match ekspresi lebih baik karena menghindari overhead menghasilkan pengecualian.
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
Karena operator downcast generik dan upcast mengandalkan inferensi jenis untuk menentukan argumen dan jenis pengembalian, Anda dapat mengganti let base1 = d1 :> Base1 dalam contoh kode sebelumnya dengan let base1: Base1 = upcast d1.
Anotasi jenis diperlukan, karena upcast dengan sendirinya tidak dapat menentukan kelas dasar.
Konversi upcast implisit
Upcast implisit disisipkan dalam situasi berikut:
Saat memberikan parameter ke fungsi atau metode dengan jenis bernama yang diketahui. Ini termasuk ketika konstruksi seperti ekspresi komputasi atau pemotongan menjadi panggilan metode.
Saat menetapkan ke atau bermutasi bidang rekaman atau properti yang memiliki jenis bernama yang diketahui.
Ketika cabang ekspresi
if/then/elseataumatchmemiliki jenis target yang diketahui yang timbul dari cabang lain atau jenis yang diketahui secara keseluruhan.Saat elemen ekspresi daftar, array, atau urutan memiliki jenis target yang diketahui.
Misalnya, pertimbangkan kode berikut:
open System
open System.IO
let findInputSource () : TextReader =
if DateTime.Now.DayOfWeek = DayOfWeek.Monday then
// On Monday a TextReader
Console.In
else
// On other days a StreamReader
File.OpenText("path.txt")
Di sini cabang komputasi bersyarat dan TextReaderStreamReader masing-masing. Pada cabang kedua, jenis target yang diketahui berasal TextReader dari anotasi jenis pada metode , dan dari cabang pertama. Ini berarti tidak ada upcast yang diperlukan pada cabang kedua.
Untuk menampilkan peringatan di setiap titik, upcast implisit tambahan digunakan, Anda dapat mengaktifkan peringatan 3388 (/warnon:3388 atau properti <WarnOn>3388</WarnOn>).
Konversi numerik implisit
F# menggunakan pelesiran eksplisit jenis numerik dalam banyak kasus melalui operator konversi. Misalnya, pelesiran eksplisit diperlukan untuk sebagian besar jenis numerik, seperti int8 atau int16, atau dari float32 ke float64, atau ketika jenis sumber atau tujuan tidak diketahui.
Namun, pellebaran implisit diizinkan untuk bilangan bulat 32-bit yang diperlebar menjadi bilangan bulat 64-bit, dalam situasi yang sama dengan upcast implisit. Misalnya, pertimbangkan bentuk API umum:
type Tensor(…) =
static member Create(sizes: seq<int64>) = Tensor(…)
Literal bilangan bulat untuk int64 dapat digunakan:
Tensor.Create([100L; 10L; 10L])
Atau literal bilangan bulat untuk int32:
Tensor.Create([int64 100; int64 10; int64 10])
Pelesiran terjadi secara otomatis untuk int32 , int32 ke int64nativeint, dan int32 ke double, ketika jenis sumber dan tujuan diketahui selama inferensi jenis. Jadi dalam kasus seperti contoh sebelumnya, int32 literal dapat digunakan:
Tensor.Create([100; 10; 10])
Anda juga dapat secara opsional mengaktifkan peringatan 3389 (/warnon:3389 atau properti <WarnOn>3389</WarnOn>) untuk menunjukkan peringatan di setiap titik pelesiran numerik implisit digunakan.
. Konversi implisit gaya NET
API .NET memungkinkan definisi op_Implicit metode statis untuk menyediakan konversi implisit antar jenis. Ini diterapkan secara otomatis dalam kode F# saat meneruskan argumen ke metode. Misalnya, pertimbangkan kode berikut yang melakukan panggilan eksplisit ke op_Implicit metode:
open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants(XName.op_Implicit "Item")
. Konversi gaya op_Implicit NET diterapkan secara otomatis untuk ekspresi argumen saat jenis tersedia untuk ekspresi sumber dan jenis target:
open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants("Item")
Anda juga dapat secara opsional mengaktifkan peringatan 3395 (/warnon:3395 atau properti <WarnOn>3395</WarnOn>) untuk menunjukkan peringatan di setiap titik a . Konversi implisit gaya NET digunakan.
. Konversi gaya op_Implicit NET juga diterapkan secara otomatis untuk ekspresi argumen non-metode dalam situasi yang sama dengan upcast implisit. Namun, ketika digunakan secara luas atau tidak pantas, konversi implisit dapat berinteraksi dengan buruk dengan inferensi jenis dan menyebabkan kode yang lebih sulit dipahami. Untuk alasan ini, ini selalu menghasilkan peringatan ketika digunakan dalam posisi non-argumen.
Untuk menunjukkan peringatan di setiap titik bahwa . Konversi implisit gaya NET digunakan untuk argumen non-metode, Anda dapat mengaktifkan peringatan 3391 (/warnon:3391 atau properti <WarnOn>3391</WarnOn>).
Ringkasan peringatan yang terkait dengan konversi
Peringatan opsional berikut disediakan untuk penggunaan konversi implisit:
-
/warnon:3388(peningkatan implisit tambahan) -
/warnon:3389(pelesiran numerik implisit) -
/warnon:3391(op_Implicitpada argumen non-metode, aktif secara default) -
/warnon:3395(op_Implicitpada argumen metode)