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.
Topik ini menjelaskan batasan yang dapat Anda terapkan ke parameter jenis generik untuk menentukan persyaratan untuk argumen jenis dalam jenis atau fungsi generik.
Sintaksis
type-parameter-list when constraint1 [ and constraint2]
Komentar
Ada beberapa batasan berbeda yang dapat Anda terapkan untuk membatasi jenis yang dapat digunakan dalam jenis generik. Tabel berikut mencantumkan dan menjelaskan batasan ini.
| Batasan | Sintaksis | Deskripsi |
|---|---|---|
| Batasan Jenis | jenis parameter :>tipe | Jenis yang disediakan harus sama dengan atau berasal dari jenis yang ditentukan, atau, jika jenisnya adalah antarmuka, jenis yang disediakan harus mengimplementasikan antarmuka. |
| Batasan Null | Parameter Jenis: null | Jenis yang disediakan harus mendukung nilai null. Ini termasuk semua jenis objek .NET tetapi bukan jenis daftar F#, tuple, fungsi, kelas, record, atau union. |
| Batasan Bukan Null | parameter tipe : tidak null | Jenis yang disediakan tidak boleh mendukung nilai null. Ini melarang jenis anotasi null dan jenis yang memiliki null sebagai nilai representasinya (seperti jenis opsi atau jenis yang ditentukan dengan atribut AllowNullLiteral). Batasan generik ini memungkinkan tipe nilai, karena tipe tersebut tidak bisa bernilai null. |
| Batasan Anggota Eksplisit | [(]parameter jenis [atau ... atau parameter jenis)] : (tanda tangan anggota) | Setidaknya salah satu argumen jenis yang disediakan harus memiliki anggota yang memiliki tanda tangan yang ditentukan; tidak ditujukan untuk penggunaan umum. Anggota harus didefinisikan secara eksplisit pada jenis atau sebagai bagian dari ekstensi jenis implisit agar menjadi target yang valid untuk Kendala Anggota Eksplisit. |
| Batasan Konstruktor | jenis-parameter : ( baru : unit -> 'a ) | Jenis yang disediakan harus memiliki konstruktor tanpa parameter. |
| Batasan Tipe Nilai | jenis parameter : struct | Tipe yang disediakan harus berupa tipe nilai .NET. |
| Batasan Tipe Referensi | tipe-parameter : bukan struct | Jenis yang disediakan harus merupakan jenis referensi .NET. |
| Batasan Jenis Enumerasi | type-parameter : enum<> jenis dasar | Jenis yang disediakan harus merupakan jenis enumerasi yang memiliki jenis yang mendasar yang ditentukan; tidak ditujukan untuk penggunaan umum. |
| Pendelegasian Batasan | type-parameter : mendelegasikan<jenis parameter tuple, > jenis pengembalian | Tipe yang disediakan harus merupakan tipe delegasi yang memiliki argumen yang ditentukan dan nilai kembalian; tidak dimaksudkan untuk penggunaan umum. |
| Batasan Perbandingan | parameter jenis : perbandingan | Jenis yang disediakan harus mendukung perbandingan. |
| Batasan Kesetaraan | parameter tipe : kesetaraan | Jenis yang disediakan harus mendukung kesetaraan. |
| Batasan Tidak Terkelola | jenis parameter : tidak dikelola | Jenis yang disediakan harus berupa jenis yang tidak dikelola. Jenis yang tidak dikelola adalah jenis primitif tertentu (sbyte, byte, char, nativeint, unativeint, float32, float, int16, uint16, int32, uint32, int64, uint64, atau decimal), jenis enumerasi, nativeptr<_>, atau struktur non-generik yang semua bidangnya adalah jenis yang tidak dikelola. |
Anda harus menambahkan batasan ketika kode Anda harus menggunakan fitur yang tersedia pada jenis batasan tetapi tidak pada jenis secara umum. Misalnya, jika Anda menggunakan batasan jenis untuk menentukan jenis kelas, Anda dapat menggunakan salah satu metode kelas tersebut dalam fungsi atau jenis generik.
Menentukan batasan terkadang diperlukan saat menulis parameter jenis secara eksplisit, karena tanpa batasan, pengkompilasi tidak memiliki cara untuk memverifikasi bahwa fitur yang Anda gunakan akan tersedia pada jenis apa pun yang mungkin disediakan pada waktu proses untuk parameter jenis.
Batasan paling umum yang Anda gunakan dalam kode F# adalah batasan jenis yang menentukan kelas dasar atau antarmuka. Batasan lainnya digunakan oleh pustaka F# untuk menerapkan fungsionalitas tertentu, seperti batasan anggota eksplisit, yang digunakan untuk menerapkan kelebihan beban operator untuk operator aritmatika, atau disediakan terutama karena F# mendukung serangkaian batasan lengkap yang didukung oleh runtime bahasa umum.
Selama proses inferensi jenis, beberapa batasan disimpulkan secara otomatis oleh pengkompilasi. Misalnya, jika Anda menggunakan operator + dalam fungsi, pengkompilasi menyimpulkan batasan anggota eksplisit pada jenis variabel yang digunakan dalam ekspresi.
Kode berikut mengilustrasikan beberapa deklarasi batasan:
// Base Type Constraint
type Class1<'T when 'T :> System.Exception> =
class end
// Interface Type Constraint
type Class2<'T when 'T :> System.IComparable> =
class end
// Null constraint
type Class3<'T when 'T : null> =
class end
// Not Null constraint
type Class4<'T when 'T : not null> =
class end
// Member constraint with instance member
type Class5<'T when 'T : (member Method1 : 'T -> int)> =
class end
// Member constraint with property
type Class6<'T when 'T : (member Property1 : int)> =
class end
// Constructor constraint
type Class7<'T when 'T : (new : unit -> 'T)>() =
member val Field = new 'T()
// Reference type constraint
type Class8<'T when 'T : not struct> =
class end
// Enumeration constraint with underlying value specified
type Class9<'T when 'T : enum<uint32>> =
class end
// 'T must implement IComparable, or be an array type with comparable
// elements, or be System.IntPtr or System.UIntPtr. Also, 'T must not have
// the NoComparison attribute.
type Class10<'T when 'T : comparison> =
class end
// 'T must support equality. This is true for any type that does not
// have the NoEquality attribute.
type Class11<'T when 'T : equality> =
class end
type Class12<'T when 'T : delegate<obj * System.EventArgs, unit>> =
class end
type Class13<'T when 'T : unmanaged> =
class end
// Member constraints with two type parameters
// Most often used with static type parameters in inline functions
let inline add(value1 : ^T when ^T : (static member (+) : ^T * ^T -> ^T), value2: ^T) =
value1 + value2
// ^T and ^U must support operator +
let inline heterogenousAdd(value1 : ^T when (^T or ^U) : (static member (+) : ^T * ^U -> ^T), value2 : ^U) =
value1 + value2
// If there are multiple constraints, use the and keyword to separate them.
type Class14<'T,'U when 'T : equality and 'U : equality> =
class end