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.
10.1 Umum
Konversi menyebabkan ekspresi dikonversi ke, atau diperlakukan sebagai, jenis tertentu; dalam kasus sebelumnya konversi dapat melibatkan perubahan representasi. Konversi dapat bersifat implisit atau eksplisit, dan ini menentukan apakah cast eksplisit diperlukan.
Contoh: Misalnya, konversi dari jenis
int
ke jenislong
bersifat implisit, sehingga ekspresi jenisint
dapat secara implisit diperlakukan sebagai jenislong
. Konversi yang berlawanan, dari jenislong
ke jenisint
, eksplisit dan sehingga diperlukan pemeran eksplisit.int a = 123; long b = a; // implicit conversion from int to long int c = (int) b; // explicit conversion from long to int
contoh akhir
Beberapa konversi didefinisikan oleh bahasa. Program juga dapat menentukan konversi mereka sendiri (§10,5).
Beberapa konversi dalam bahasa ditentukan dari ekspresi ke jenis, yang lain dari jenis ke jenis. Konversi dari jenis berlaku untuk semua ekspresi yang memiliki jenis tersebut.
Contoh:
enum Color { Red, Blue, Green } // The expression 0 converts implicitly to enum types Color c0 = 0; // Other int expressions need explicit conversion Color c1 = (Color)1; // Conversion from null expression (no type) to string string x = null; // Conversion from lambda expression to delegate type Func<int, int> square = x => x * x;
contoh akhir
10.2 Konversi implisit
10.2.1 Umum
Konversi berikut diklasifikasikan sebagai konversi implisit:
- Konversi identitas (§10.2.2)
- Konversi numerik implisit (§10.2.3)
- Konversi enumerasi implisit (§10.2.4)
- Konversi string terinterpolasi implisit (§10.2.5)
- Konversi referensi implisit (§10.2.8)
- Konversi tinju (§10.2.9)
- Konversi dinamis implisit (§10.2.10)
- Konversi parameter jenis implisit (§10.2.12)
- Konversi ekspresi konstanta implisit (§10.2.11)
- Konversi implisit yang ditentukan pengguna (termasuk diangkat) (§10.2.14)
- Konversi fungsi anonim (§10.2.15)
- Konversi grup metode (§10.2.15)
- Konversi harfiah null (§10.2.7)
- Konversi implisit nullable (§10.2.6)
- Konversi tuple implisit (§10.2.13)
- Konversi literal default (§10.2.16)
- Konversi lemparan implisit (§10.2.17)
Konversi implisit dapat terjadi dalam berbagai situasi, termasuk pemanggilan anggota fungsi (§12.6.6), ekspresi cast (§12.9.7), dan penugasan (§12,21).
Konversi implisit yang telah ditentukan sebelumnya selalu berhasil dan tidak pernah menyebabkan pengecualian dilemparkan.
Catatan: Konversi implisit yang ditentukan pengguna yang dirancang dengan benar juga harus menunjukkan karakteristik ini. catatan akhir
Untuk tujuan konversi, jenis object
dan dynamic
dapat dikonversi identitas (§10.2.2).
Namun, konversi dinamis (§10.2.10) hanya berlaku untuk ekspresi jenis dynamic
(§8.2.4).
10.2.2 Konversi identitas
Konversi identitas dikonversi dari jenis apa pun ke jenis yang sama atau jenis yang setara pada runtime. Salah satu alasan konversi ini ada sehingga jenis T
atau ekspresi jenis T
dapat dikatakan dapat dikonversi ke T
dirinya sendiri. Konversi identitas berikut ada:
- Antara
T
danT
, untuk semua jenisT
. - Antara
T
danT?
untuk jenisT
referensi apa pun . - Antara
object
dandynamic
. - Antara semua jenis tuple dengan aritas yang sama, dan jenis konstruksi yang sesuai
ValueTuple<...>
, ketika konversi identitas ada di antara setiap pasangan jenis elemen yang sesuai. - Antara jenis yang dibangun dari jenis generik yang sama di mana ada konversi identitas antara setiap argumen jenis yang sesuai.
Contoh: Berikut ini menggambarkan sifat rekursif dari aturan ketiga:
(int a , string b) t1 = (1, "two"); (int c, string d) t2 = (3, "four"); // Identity conversions exist between // the types of t1, t2, and t3. var t3 = (5, "six"); t3 = t2; t2 = t1; var t4 = (t1, 7); var t5 = (t2, 8); // Identity conversions exist between // the types of t4, t5, and t6. var t6 =((8, "eight"), 9); t6 = t5; t5 = t4;
Jenis tuple
t1
,t2
dant3
semuanya memiliki dua elemen: diikutiint
olehstring
. Jenis elemen tuple dapat sendiri dengan tuple, seperti dalamt4
,t5
, dant6
. Konversi identitas ada di antara setiap pasangan jenis elemen yang sesuai, termasuk tuple berlapis, oleh karena itu konversi identitas ada di antara jenis tuplet4
, ,t5
dant6
.contoh akhir
Semua konversi identitas bersifat simetris. Jika konversi identitas ada dari T₁
ke T₂
, maka konversi identitas ada dari T₂
ke T₁
. Dua jenis dapat dikonversi identitas ketika konversi identitas ada di antara dua jenis.
Dalam kebanyakan kasus, konversi identitas tidak berpengaruh pada runtime. Namun, karena operasi floating point dapat dilakukan pada presisi yang lebih tinggi daripada yang ditentukan oleh jenisnya (§8.3.7), penugasan hasilnya dapat mengakibatkan hilangnya presisi, dan cast eksplisit dijamin untuk mengurangi presisi terhadap apa yang ditentukan oleh jenis (§12.9.7).
10.2.3 Konversi numerik implisit
Konversi numerik implisit adalah:
- Dari
sbyte
keshort
,int
,long
,float
,double
, ataudecimal
. - Dari
byte
keshort
,ushort
,int
,uint
,long
,ulong
,float
,double
, ataudecimal
. - Dari
short
keint
,long
,float
,double
, ataudecimal
. - Dari
ushort
keint
,uint
,long
,ulong
,float
,double
, ataudecimal
. - Dari
int
kelong
,float
,double
, ataudecimal
. - Dari
uint
kelong
,ulong
,float
,double
, ataudecimal
. - Dari
long
kefloat
,double
, ataudecimal
. - Dari
ulong
kefloat
,double
, ataudecimal
. - Dari
char
keushort
,int
,uint
,long
,ulong
,float
,double
, ataudecimal
. - Dari
float
sampaidouble
.
Konversi dari int
, , uint
long
atau ulong
ke float
dan dari long
atau ulong
ke double
dapat menyebabkan hilangnya presisi, tetapi tidak akan pernah menyebabkan hilangnya besaran. Konversi numerik implisit lainnya belum pernah kehilangan informasi apa pun.
Tidak ada konversi implisit yang telah ditentukan sebelumnya ke char
jenis , sehingga nilai jenis integral lainnya tidak secara otomatis dikonversi ke jenis .char
10.2.4 Konversi enumerasi implisit
Konversi enumerasi implisit memungkinkan constant_expression (§12,23) dengan jenis bilangan bulat apa pun dan nilai nol yang akan dikonversi ke enum_type apa pun dan ke nullable_value_type yang jenis yang mendasarnya adalah enum_type. Dalam kasus terakhir, konversi dievaluasi dengan mengonversi ke enum_type yang mendasar dan membungkus hasilnya (§8.3.12).
10.2.5 Konversi string terinterpolasi implisit
Konversi string terinterpolasi implisit mengizinkan interpolated_string_expression (§12.8.3) untuk dikonversi ke System.IFormattable
atau System.FormattableString
(yang mengimplementasikan System.IFormattable
).
Ketika konversi ini diterapkan, nilai string tidak terdiri dari string terinterpolasi. Sebagai gantinya, instans System.FormattableString
dibuat, seperti yang dijelaskan lebih lanjut dalam §12.8.3.
10.2.6 Konversi implisit nullable
Konversi implisit nullable adalah konversi nullable (§10.6.1) yang berasal dari konversi implisit yang telah ditentukan sebelumnya.
10.2.7 Konversi harfiah null
Konversi implisit ada dari null
literal ke jenis referensi apa pun atau jenis nilai nullable. Konversi ini menghasilkan referensi null jika jenis target adalah jenis referensi, atau nilai null (§8.3.12) dari jenis nilai nullable yang diberikan.
10.2.8 Konversi referensi implisit
Konversi referensi implisit adalah:
- Dari reference_type ke
object
dandynamic
. - Dari class_type
S
hingga class_type, yang disediakanT
berasal dariS
. - Dari class_typehingga interface_type
S
, yang disediakan mengimplementasikanT
. - Dari interface_type
S
hingga interface_type, yang disediakanT
berasal dariS
. -
dengan jenis
S
elemen keSᵢ
dengan jenisT
elemen , asalkan semua hal berikut ini benar:-
S
danT
hanya berbeda dalam jenis elemen. Dengan kata lain,S
danT
memiliki jumlah dimensi yang sama. - Konversi referensi implisit ada dari
Sᵢ
keTᵢ
.
-
- Dari jenis
S[]
array dimensi tunggal keSystem.Collections.Generic.IList<T>
,System.Collections.Generic.IReadOnlyList<T>
, dan antarmuka dasarnya, asalkan ada konversi identitas atau referensi implisit dariS
keT
. - Dari array_type apa pun hingga
System.Array
dan antarmuka yang diimplementasikannya. - Dari delegate_type apa pun hingga
System.Delegate
dan antarmuka yang diimplementasikannya. - Dari literal null (§6.4.5.7) hingga jenis referensi apa pun.
- Dari reference_type apa pun
- Dari reference_type apa pun
- Konversi implisit yang melibatkan parameter jenis yang dikenal sebagai jenis referensi. Lihat §10.2.12 untuk detail selengkapnya tentang konversi implisit yang melibatkan parameter jenis.
Konversi referensi implisit adalah konversi antara reference_typeyang dapat terbukti selalu berhasil, dan karenanya tidak memerlukan pemeriksaan pada run-time.
Konversi referensi, implisit atau eksplisit, tidak pernah mengubah identitas referensial objek yang dikonversi.
Catatan: Dengan kata lain, sementara konversi referensi dapat mengubah jenis referensi, itu tidak pernah mengubah jenis atau nilai objek yang dirujuk. catatan akhir
10.2.9 Konversi Tinju
Konversi tinju memungkinkan value_type dikonversi secara implisit ke reference_type. Konversi tinju berikut ada:
- Dari value_type apa pun
- Dari value_type apa pun
- Dari enum_type apa pun
- Dari non_nullable_value_type apa pun hingga interface_type apa pun yang diterapkan oleh non_nullable_value_type.
- Dari non_nullable_value_type apa pun
- Dari non_nullable_value_type apa pun
- Dari nullable_value_type apa pun ke reference_type mana pun di mana ada konversi tinju dari jenis nullable_value_type yang mendasar ke reference_type.
- Dari parameter jenis yang tidak diketahui sebagai jenis referensi ke jenis apa pun sehingga konversi diizinkan oleh §10.2.12.
Tinju nilai jenis nilai yang tidak dapat diubah ke null terdiri dari mengalokasikan instans objek dan menyalin nilai ke dalam instans tersebut.
Tinju nilai nullable_value_type menghasilkan referensi null jika itu adalah nilai null (HasValue
salah), atau hasil pembongkaran dan tinju nilai yang mendasar sebaliknya.
Catatan: Proses tinju dapat dibayangkan dalam hal keberadaan kelas tinju untuk setiap jenis nilai. Misalnya, pertimbangkan
struct S
untuk menerapkan antarmukaI
, dengan kelas tinju yang disebutS_Boxing
.interface I { void M(); } struct S : I { public void M() { ... } } sealed class S_Boxing : I { S value; public S_Boxing(S value) { this.value = value; } public void M() { value.M(); } }
Tinju nilai
v
jenisS
sekarang terdiri dari menjalankan ekspresinew S_Boxing(v)
dan mengembalikan instans yang dihasilkan sebagai nilai dari jenis target konversi. Dengan demikian, pernyataanS s = new S(); object box = s;
dapat dianggap mirip dengan:
S s = new S(); object box = new S_Boxing(s);
Jenis tinju yang dibayangkan yang dijelaskan di atas sebenarnya tidak ada. Sebagai gantinya, nilai berkotak jenis
S
memiliki jenisS
runtime , dan pemeriksaan jenis runtime menggunakanis
operator dengan jenis nilai sebagai uji operand kanan apakah operand kiri adalah versi kotak dari operand kanan. Contohnya,int i = 123; object box = i; if (box is int) { Console.Write("Box contains an int"); }
akan menghasilkan yang berikut:
Box contains an int
Konversi tinju menyiratkan pembuatan salinan nilai yang dikotak. Ini berbeda dari konversi reference_type ke jenis
object
, di mana nilai terus mereferensikan instans yang sama dan hanya dianggap sebagai jenisobject
yang kurang diturunkan . Misalnya, berikut inistruct Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { void M() { Point p = new Point(10, 10); object box = p; p.x = 20; Console.Write(((Point)box).x); } }
akan menghasilkan nilai 10 pada konsol karena operasi tinju implisit yang terjadi dalam penugasan
p
menyebabkanbox
nilaip
disalin. TelahPoint
dinyatakan sebagaiclass
gantinya, nilai 20 akan menjadi output karenap
danbox
akan mereferensikan instans yang sama.Analogi kelas tinju tidak boleh digunakan sebagai lebih dari alat bermanfaat untuk menggambarkan cara kerja tinju secara konseptual. Ada banyak perbedaan halus antara perilaku yang dijelaskan oleh spesifikasi ini dan perilaku yang akan mengakibatkan tinju diimplementasikan dengan tepat dengan cara ini.
catatan akhir
10.2.10 Konversi dinamis implisit
Konversi dinamis implisit ada dari ekspresi jenis dinamis ke jenis T
apa pun . Konversi terikat secara dinamis §12.3.3, yang berarti bahwa konversi implisit akan dicari pada run-time dari jenis run-time ekspresi ke T
. Jika tidak ada konversi yang ditemukan, pengecualian run-time akan dilemparkan.
Konversi implisit ini tampaknya melanggar saran di awal §10.2 bahwa konversi implisit tidak boleh menyebabkan pengecualian. Namun, itu bukan konversi itu sendiri, tetapi temuan konversi yang menyebabkan pengecualian. Risiko pengecualian run-time melekat dalam penggunaan pengikatan dinamis. Jika pengikatan dinamis konversi tidak diinginkan, ekspresi dapat terlebih dahulu dikonversi ke object
, lalu ke jenis yang diinginkan.
Contoh: Berikut ini menggambarkan konversi dinamis implisit:
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
Penugasan ke
s2
dani
keduanya menggunakan konversi dinamis implisit, di mana pengikatan operasi ditangguhkan hingga run-time. Pada run-time, konversi implisit dicari dari jenisd
run-time (string
) ke jenis target. Konversi ditemukan tetapistring
tidak keint
.contoh akhir
10.2.11 Konversi ekspresi konstanta implisit
Konversi ekspresi konstanta implisit mengizinkan konversi berikut:
- Jenis
- Constant_expression jenis
long
dapat dikonversi ke jenisulong
, asalkan nilai constant_expression tidak negatif.
10.2.12 Konversi implisit yang melibatkan parameter jenis
yang dikenal sebagai jenis referensi (T
), konversi referensi implisit berikut (§10.2.8) ada:
- Dari ke kelas
T
dasar yang efektif , dariC
ke kelas dasar apa pun ,T
dan dariC
ke antarmuka apa pun yang diimplementasikan olehT
.C
- Dari
T
ke interface_typeI
dalamT
set antarmuka efektif dan dariT
ke antarmuka dasar apa pun dariI
. - Dari
T
ke parameterU
jenis yang disediakan yangT
bergantung padaU
(§15.2.5).Catatan: Karena
T
dikenal sebagai jenis referensi, dalam lingkupT
, jenisU
run-time akan selalu menjadi jenis referensi, bahkan jikaU
tidak diketahui sebagai jenis referensi pada waktu kompilasi. catatan akhir - Dari harfiah null (§6.4.5.7) hingga T.
yang T
diketahui sebagai jenis referensi §15.2.5, konversi berikut yang melibatkan dianggap sebagai konversi tinju (T
) pada waktu kompilasi. Pada run-time, jika T
adalah jenis nilai, konversi dijalankan sebagai konversi tinju. Pada run-time, jika T
merupakan jenis referensi, konversi dijalankan sebagai konversi referensi implisit atau konversi identitas.
- Dari ke kelas
T
dasar yang efektif , dariC
ke kelas dasar apa pun ,T
dan dariC
ke antarmuka apa pun yang diimplementasikan olehT
.C
Catatan:
C
akan menjadi salah satu jenisSystem.Object
, ,System.ValueType
atauSystem.Enum
(jika tidakT
, akan diketahui sebagai jenis referensi). catatan akhir - Dari
T
ke interface_typeI
dalamT
set antarmuka efektif dan dariT
ke antarmuka dasar apa pun dariI
.
yang T
diketahui sebagai jenis referensi, ada konversi implisit dari ke parameter T
jenis yang disediakan U
tergantung pada T
. Pada run-time, jika T
adalah jenis nilai dan U
merupakan jenis referensi, konversi dijalankan sebagai konversi tinju. Pada run-time, jika dan T
U
merupakan jenis nilai, maka T
dan U
harus jenis yang sama dan tidak ada konversi yang dilakukan. Pada run-time, jika T
adalah jenis referensi, maka U
tentu juga merupakan jenis referensi dan konversi dijalankan sebagai konversi referensi implisit atau konversi identitas (§15.2.5).
Konversi implisit lebih lanjut berikut ada untuk parameter T
jenis tertentu :
- Dari
T
ke jenisS
referensi jika memiliki konversi implisit ke jenisS₀
referensi danS₀
memiliki konversi identitas keS
. Pada run-time, konversi dijalankan dengan cara yang sama seperti konversi keS₀
. - Dari
T
ke jenisI
antarmuka jika memiliki konversi implisit ke jenisI₀
antarmuka , danI₀
dapat dikonversi varians keI
(§18.2.3.3). Pada run-time, jikaT
adalah jenis nilai, konversi dijalankan sebagai konversi tinju. Jika tidak, konversi dijalankan sebagai konversi referensi implisit atau konversi identitas.
Dalam semua kasus, aturan memastikan bahwa konversi dijalankan sebagai konversi tinju jika dan hanya jika pada run-time konversi berasal dari jenis nilai ke jenis referensi.
10.2.13 Konversi tuple implisit
Konversi implisit ada dari ekspresi E
tuple ke jenis T
tuple jika E
memiliki aritas yang sama dengan T
dan konversi implisit ada dari setiap elemen ke E
jenis elemen yang sesuai di T
. Konversi dilakukan dengan membuat instans jenis T
yang System.ValueTuple<...>
sesuai, dan menginisialisasi setiap bidangnya secara berurutan dari kiri ke kanan dengan mengevaluasi ekspresi E
elemen tuple yang sesuai , mengonversinya ke jenis elemen yang sesuai menggunakan T
konversi implisit yang ditemukan, dan menginisialisasi bidang dengan hasilnya.
Jika nama elemen dalam ekspresi tuple tidak cocok dengan nama elemen yang sesuai dalam jenis tuple, peringatan akan dikeluarkan.
Contoh:
(int, string) t1 = (1, "One"); (byte, string) t2 = (2, null); (int, string) t3 = (null, null); // Error: No conversion (int i, string s) t4 = (i: 4, "Four"); (int i, string) t5 = (x: 5, s: "Five"); // Warning: Names are ignored
Deklarasi
t1
,t2
,t4
dant5
semuanya valid, karena konversi implisit ada dari ekspresi elemen ke jenis elemen yang sesuai. Deklarasit3
tidak valid, karena tidak ada konversi darinull
keint
. Deklarasit5
menyebabkan peringatan karena nama elemen dalam ekspresi tuple berbeda dari yang ada di jenis tuple.contoh akhir
10.2.14 Konversi implisit yang ditentukan pengguna
Konversi implisit yang ditentukan pengguna terdiri dari konversi implisit standar opsional, diikuti dengan eksekusi operator konversi implisit yang ditentukan pengguna, diikuti oleh konversi implisit standar opsional lainnya. Aturan yang tepat untuk mengevaluasi konversi implisit yang ditentukan pengguna dijelaskan dalam §10.5.4.
10.2.15 Konversi fungsi anonim dan konversi grup metode
Fungsi anonim dan grup metode tidak memiliki jenis dalam dan dari diri mereka sendiri, tetapi mungkin secara implisit dikonversi untuk mendelegasikan jenis. Selain itu, beberapa ekspresi lambda dapat dikonversi secara implisit ke jenis pohon ekspresi. Konversi fungsi anonim dijelaskan secara lebih rinci dalam §10,7 dan konversi grup metode dalam §10,8.
10.2.16 Konversi literal default
Konversi implisit ada dari default_literal (§12.8.21) ke jenis apa pun. Konversi ini menghasilkan nilai default (§9,3) dari jenis yang disimpulkan.
10.2.17 Konversi lemparan implisit
Meskipun ekspresi lemparan tidak memiliki jenis, ekspresi mungkin dikonversi secara implisit ke jenis apa pun.
10.3 Konversi eksplisit
10.3.1 Umum
Konversi berikut diklasifikasikan sebagai konversi eksplisit:
- Semua konversi implisit (§10.2)
- Konversi numerik eksplisit (§10.3.2)
- Konversi enumerasi eksplisit (§10.3.3)
- Konversi nullable eksplisit (§10.3.4)
- Konversi tuple eksplisit (§10.3.6)
- Konversi referensi eksplisit (§10.3.5)
- Konversi antarmuka eksplisit
- Membatalkan konversi kotak (§10.3.7)
- Konversi parameter jenis eksplisit (§10.3.8)
- Konversi eksplisit yang ditentukan pengguna (§10.3.9)
Konversi eksplisit dapat terjadi dalam ekspresi pemeran (§12.9.7).
Kumpulan konversi eksplisit mencakup semua konversi implisit.
Catatan: Ini, misalnya, memungkinkan cast eksplisit digunakan ketika konversi identitas implisit ada, untuk memaksa pemilihan metode tertentu kelebihan beban. catatan akhir
Konversi eksplisit yang bukan konversi implisit adalah konversi yang tidak dapat dibuktikan selalu berhasil, konversi yang diketahui mungkin kehilangan informasi, dan konversi di seluruh domain jenis yang cukup berbeda untuk merit notasi eksplisit.
10.3.2 Konversi numerik eksplisit
Konversi numerik eksplisit adalah konversi dari numeric_type ke numeric_type lain yang konversi numerik implisitnya (§10.2.3) belum ada:
- Dari
sbyte
kebyte
,ushort
,uint
,ulong
, atauchar
. - Dari
byte
kesbyte
atauchar
. - Dari
short
kesbyte
,byte
,ushort
,uint
,ulong
, atauchar
. - Dari
ushort
kesbyte
,byte
,short
, atauchar
. - Dari
int
kesbyte
,byte
,short
,ushort
,uint
,ulong
, atauchar
. - Dari
uint
kesbyte
,byte
,short
,ushort
,int
, atauchar
. - Dari
long
kesbyte
,byte
,short
,ushort
,int
,uint
,ulong
, atauchar
. - Dari
ulong
kesbyte
,byte
,short
,ushort
,int
,uint
,long
, atauchar
. - Dari
char
kesbyte
,byte
, ataushort
. - Dari
float
kesbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
, ,char
, ataudecimal
. - Dari
double
kesbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
, ,float
, ataudecimal
. - Dari
decimal
kesbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
, ,float
, ataudouble
.
Karena konversi eksplisit mencakup semua konversi numerik implisit dan eksplisit, selalu dimungkinkan untuk mengonversi dari numeric_type apa pun ke numeric_type lain menggunakan ekspresi pemeran (§12.9.7).
Konversi numerik eksplisit mungkin kehilangan informasi atau mungkin menyebabkan pengecualian dilemparkan. Konversi numerik eksplisit diproses sebagai berikut:
- Untuk konversi dari jenis integral ke jenis integral lain, pemrosesan tergantung pada konteks pemeriksaan luapan (§12.8.20) di mana konversi terjadi:
-
checked
Dalam konteks, konversi berhasil jika nilai operand sumber berada dalam rentang jenis tujuan, tetapi melemparkanSystem.OverflowException
jika nilai operand sumber berada di luar rentang jenis tujuan. - Dalam konteks
unchecked
, konversi selalu berhasil, dan berlanjut sebagai berikut.- Jika jenis sumber lebih besar dari jenis tujuan, maka nilai sumber dipotong dengan membuang bit "ekstra" yang paling signifikan. Hasilnya kemudian diperlakukan sebagai nilai dari jenis tujuannya.
- Jika jenis sumber berukuran sama dengan jenis tujuan, maka nilai sumber diperlakukan sebagai nilai dari jenis tujuan
-
- Untuk konversi dari
decimal
ke jenis integral, nilai sumber dibulatkan ke nol ke nilai integral terdekat, dan nilai integral ini menjadi hasil konversi. Jika nilai integral yang dihasilkan berada di luar rentang jenis tujuan, akanSystem.OverflowException
dilemparkan. - Untuk konversi dari
float
ataudouble
ke jenis integral, pemrosesan tergantung pada konteks pemeriksaan luapan (§12.8.20) tempat konversi berlangsung:- Dalam konteks yang dicentang, konversi berlanjut sebagai berikut:
- Jika nilai operand adalah NaN atau tak terbatas, akan
System.OverflowException
dilemparkan. - Jika tidak, operand sumber dibulatkan menuju nol ke nilai integral terdekat. Jika nilai integral ini berada dalam rentang jenis tujuan, maka nilai ini adalah hasil konversi.
- Jika tidak, dilemparkan
System.OverflowException
.
- Jika nilai operand adalah NaN atau tak terbatas, akan
- Dalam konteks yang tidak dicentang, konversi selalu berhasil, dan berlanjut sebagai berikut.
- Jika nilai operand adalah NaN atau tak terbatas, hasil konversi adalah nilai yang tidak ditentukan dari jenis tujuan.
- Jika tidak, operand sumber dibulatkan menuju nol ke nilai integral terdekat. Jika nilai integral ini berada dalam rentang jenis tujuan, maka nilai ini adalah hasil konversi.
- Jika tidak, hasil konversi adalah nilai yang tidak ditentukan dari jenis tujuan.
- Dalam konteks yang dicentang, konversi berlanjut sebagai berikut:
- Untuk konversi dari
double
kefloat
, nilai dibulatkandouble
ke nilai terdekatfloat
.double
Jika nilai terlalu kecil untuk diwakili sebagaifloat
, hasilnya menjadi nol dengan tanda yang sama dengan nilai . Jika besarnyadouble
nilai terlalu besar untuk diwakili sebagaifloat
, hasilnya menjadi tak terbatas dengan tanda yang sama dengan nilai . Jika nilainyadouble
adalah NaN, hasilnya juga NaN. - Untuk konversi dari atau ke , nilai sumber dikonversi ke
float
representasi dan dibulatkan ke angka terdekat jika diperlukan (double
).decimal
decimal
- Jika nilai sumber terlalu kecil untuk direpresentasikan sebagai
decimal
, hasilnya menjadi nol, mempertahankan tanda nilai asli jikadecimal
mendukung nilai nol yang ditandatangani. - Jika besarnya nilai sumber terlalu besar untuk direpresentasikan sebagai
decimal
, atau nilai tersebut tidak terbatas, hasilnya adalah infinity mempertahankan tanda nilai asli, jika representasi desimal mendukung tak terbatas; jika tidak, System.OverflowException akan dilemparkan. - Jika nilai sumber adalah NaN, hasilnya adalah NaN jika representasi desimal mendukung NaN; jika tidak, System.OverflowException dilemparkan.
- Jika nilai sumber terlalu kecil untuk direpresentasikan sebagai
- Untuk konversi dari
decimal
kefloat
ataudouble
, nilai dibulatkandecimal
ke nilai terdekatdouble
ataufloat
. Jika besarnya nilai sumber terlalu besar untuk diwakili dalam jenis target, atau nilai tersebut tidak terbatas, hasilnya adalah infinity mempertahankan tanda nilai asli. Jika nilai sumber adalah NaN, hasilnya adalah NaN. Meskipun konversi ini mungkin kehilangan presisi, itu tidak pernah menyebabkan pengecualian dilemparkan.
Catatan:
decimal
Jenis ini tidak diperlukan untuk mendukung nilai infinities atau NaN tetapi dapat melakukannya; rentangnya mungkin lebih kecil dari rentangfloat
dandouble
, tetapi tidak dijamin. Untukdecimal
representasi tanpa nilai infinities atau NaN, dan dengan rentang yang lebih kecil darifloat
, hasil konversi daridecimal
ke ataufloat
double
tidak akan pernah tak terbatas atau NaN. catatan akhir
10.3.3 Konversi enumerasi eksplisit
Konversi enumerasi eksplisit adalah:
- Dari
sbyte
, ,byte
short
,ushort
,int
uint
, ,long
,ulong
,char
,float
,double
, , ataudecimal
ke enum_type apa pun. - Dari enum_type apa pun
- Dari enum_type ke enum_type lainnya.
Konversi enumerasi eksplisit antara dua jenis diproses dengan memperlakukan enum_type yang berpartisipasi sebagai jenis yang mendasar dari enum_type tersebut, lalu melakukan konversi numerik implisit atau eksplisit antara jenis yang dihasilkan.
Contoh: Mengingat enum_type
E
dengan jenisint
yang mendasar , konversi dariE
kebyte
diproses sebagai konversi numerik eksplisit (§10,3,2) dariint
kebyte
, dan konversi daribyte
keE
diproses sebagai konversi numerik implisit (§10,2,3) daribyte
keint
. contoh akhir
10.3.4 Konversi nullable eksplisit
Konversi nullable eksplisit adalah konversi nullable (§10.6.1) yang berasal dari konversi eksplisit dan implisit yang telah ditentukan sebelumnya.
10.3.5 Konversi referensi eksplisit
Konversi referensi eksplisit adalah:
- Dari objek ke reference_type lainnya.
- Dari class_typehingga class_type
S
, yang disediakan adalah kelas dasar .T
- Dari class_type apa pun
S
- Dari interface_type apa pun
S
- Dari interface_type
S
hingga interface_type, yang disediakanT
tidak berasal dariS
. -
dengan jenis
S
elemen keSᵢ
dengan jenisT
elemen , asalkan semua hal berikut ini benar:-
S
danT
hanya berbeda dalam jenis elemen. Dengan kata lain,S
danT
memiliki jumlah dimensi yang sama. - Konversi referensi eksplisit ada dari
Sᵢ
keTᵢ
.
-
- Dari
System.Array
dan antarmuka yang diimplementasikannya, ke array_type apa pun. - Dari array_type
S[]
ada konversi identitas atau konversi referensi eksplisit dariSystem.Collections.Generic.IList<T>
keSystem.Collections.Generic.IReadOnlyList<T>
. - Dari
System.Collections.Generic.IList<S>
,System.Collections.Generic.IReadOnlyList<S>
, dan antarmuka dasarnya ke jenisT[]
array dimensi tunggal , asalkan ada konversi identitas atau konversi referensi eksplisit dariS
ke T. - Dari
System.Delegate
dan antarmuka yang diimplementasikannya ke delegate_type apa pun. - Dari jenis
S
referensi ke jenisT
referensi jika memiliki konversi referensi eksplisit dariS
ke jenisT₀
referensi danT₀
dan ada konversi identitas dariT₀
keT
. - Dari jenis
S
referensi ke antarmuka atau jenisT
delegasi jika ada konversi referensi eksplisit dariS
ke antarmuka atau jenisT₀
delegasi dan dapatT₀
dikonversi varians keT
atauT
dapat dikonversi varians keT₀
§18.2.3.3. - Dari
D<S₁...Sᵥ>
keD<T₁...Tᵥ>
tempatD<X₁...Xᵥ>
adalah jenis delegasi generik,D<S₁...Sᵥ>
tidak kompatibel dengan atau identikD<T₁...Tᵥ>
dengan , dan untuk setiap parameterXᵢ
jenis penangguhanD
berikut:- Jika
Xᵢ
invarian, makaSᵢ
identik denganTᵢ
. - Jika
Xᵢ
kovarian, maka ada konversi identitas, konversi referensi implisit, atau konversi referensi eksplisit dariSᵢ
keTᵢ
. - Jika
Xᵢ
kontravarian, makaSᵢ
danTᵢ
merupakan jenis referensi yang identik atau keduanya.
- Jika
- Konversi eksplisit yang melibatkan parameter jenis yang diketahui sebagai jenis referensi. Untuk detail selengkapnya tentang konversi eksplisit yang melibatkan parameter jenis, lihat §10.3.8.
Konversi referensi eksplisit adalah konversi antara reference_typeyang memerlukan pemeriksaan run-time untuk memastikan konversi tersebut benar.
Agar konversi referensi eksplisit berhasil pada run-time, nilai operand sumber harus , atau jenis objek yang direferensikan null
oleh operand sumber adalah jenis yang dapat dikonversi ke jenis tujuan dengan konversi referensi implisit (§10.2.8). Jika konversi referensi eksplisit gagal, akan System.InvalidCastException
dilemparkan.
Catatan: Konversi referensi, implisit atau eksplisit, tidak pernah mengubah nilai referensi itu sendiri (§8.2.1), hanya jenisnya; tidak mengubah jenis atau nilai objek yang dirujuk. catatan akhir
10.3.6 Konversi tuple eksplisit
Konversi eksplisit ada dari ekspresi E
tuple ke jenis T
tuple jika E
memiliki aritas yang sama dengan T
dan konversi implisit atau eksplisit ada dari setiap elemen ke E
jenis elemen yang sesuai di T
. Konversi dilakukan dengan membuat instans jenis T
yang System.ValueTuple<...>
sesuai, dan menginisialisasi setiap bidangnya secara berurutan dari kiri ke kanan dengan mengevaluasi ekspresi elemen tuple yang sesuai dari E
, mengonversinya ke jenis elemen yang sesuai menggunakan T
konversi eksplisit yang ditemukan, dan menginisialisasi bidang dengan hasilnya.
10.3.7 Konversi unboxing
Konversi pembatalan kotak memungkinkan reference_type dikonversi secara eksplisit ke value_type. Konversi pembukaan kotak berikut ada:
- Dari jenis
object
ke value_type apa pun. - Dari jenis
System.ValueType
ke value_type apa pun. - Dari jenis
System.Enum
ke enum_type apa pun. - Dari interface_type apa pun hingga non_nullable_value_type apa pun yang mengimplementasikan interface_type.
- Dari interface_type apa pun
I
ke non_nullable_value_type di mana ada konversi pembukaan kotak dari interface_typeI₀
ke jenis non_nullable_value dan konversi identitas dariI
keI₀
. - Dari interface_type
I
apa pun ke non_nullable_value_type di mana ada konversi pembatalan pengemasan dari interface_typeI₀
ke non_nullable_value_type danI₀
dapat dikonversi varians keI
atauI
dapat dikonversi varians keI₀
(§18.2.3.3). - Dari reference_type apa pun ke nullable_value_type mana pun di mana ada konversi pembukaan kotak dari reference_type ke non_nullable_value_type yang mendasar dari nullable_value_type.
- Dari parameter jenis yang tidak diketahui sebagai jenis nilai ke jenis apa pun sehingga konversi diizinkan oleh §10.3.8.
Operasi pembukaan kotak ke non_nullable_value_type terdiri dari pemeriksaan pertama bahwa instans objek adalah nilai kotak dari non_nullable_value_type yang diberikan, lalu menyalin nilai dari instans.
Membuka kotak ke nullable_value_type menghasilkan nilai null nullable_value_type jika operand sumber adalah null
, atau hasil yang dibungkus dari membuka kotak instans objek ke jenis nullable_value_type yang mendasar jika tidak.
Catatan: Mengacu pada kelas tinju imajiner yang dijelaskan dalam §10.2.9, konversi pembatalan kotak objek ke value_type
S
terdiri dari menjalankan ekspresi((S_Boxing)box).value
. Dengan demikian, pernyataanobject box = new S(); S s = (S)box;
secara konseptual sesuai dengan
object box = new S_Boxing(new S()); S s = ((S_Boxing)box).value;
catatan akhir
Agar konversi pembukaan kotak ke non_nullable_value_type tertentu berhasil pada run-time, nilai operand sumber harus menjadi referensi ke nilai kotak dari non_nullable_value_type tersebut. Jika operand sumber adalah null
dilemparkan System.NullReferenceException
. Jika operand sumber adalah referensi ke objek yang tidak kompatibel, akan System.InvalidCastException
dilemparkan.
Agar konversi pembukaan kotak ke nullable_value_type tertentu berhasil pada run-time, nilai operand sumber harus null atau referensi ke nilai kotak dari non_nullable_value_type yang mendasari nullable_value_type. Jika operand sumber adalah referensi ke objek yang tidak kompatibel, akan System.InvalidCastException
dilemparkan.
10.3.8 Konversi eksplisit yang melibatkan parameter jenis
yang dikenal sebagai jenis referensi (T
), konversi referensi eksplisit berikut (§10.3.5) ada:
- Dari kelas
C
dasar yang efektif dariT
keT
dan dari kelas dasar apa pun hinggaC
T
. - Dari interface_type apa pun hingga
T
. - Dari
T
ke interface_typeyang disediakan belum ada konversi referensi implisit dariI
keT
. -
Dari type_parameter
U
yangT
disediakan tergantungT
padaU
(§15.2.5).Catatan: Karena
T
dikenal sebagai jenis referensi, dalam cakupanT
, jenis run-time Anda akan selalu menjadi jenis referensi, bahkan jikaU
tidak diketahui sebagai jenis referensi pada waktu kompilasi. catatan akhir
Untuk type_parameterT
yang tidak diketahui sebagai jenis referensi (§15.2.5), konversi berikut yang melibatkan T
dianggap sebagai konversi pembuka kotak (§10.3.7) pada waktu kompilasi. Pada run-time, jika T
adalah jenis nilai, konversi dijalankan sebagai konversi unboxing. Pada run-time, jika T
merupakan jenis referensi, konversi dijalankan sebagai konversi referensi eksplisit atau konversi identitas.
- Dari kelas
C
dasar yang efektif dariT
keT
dan dari kelas dasar apa pun hinggaC
T
.Catatan: C akan menjadi salah satu jenis
System.Object
, ,System.ValueType
atauSystem.Enum
(jika tidakT
, akan diketahui sebagai jenis referensi). catatan akhir - Dari interface_type apa pun hingga
T
.
yang T
diketahui sebagai jenis referensi (§15.2.5), konversi eksplisit berikut ada:
- Dari
T
ke interface_typebelum ada konversi implisit dariI
keT
. Konversi ini terdiri dari konversi tinju implisit (§10.2.9) dariT
keobject
diikuti dengan konversi referensi eksplisit dariobject
keI
. Pada run-time, jikaT
adalah jenis nilai, konversi dijalankan sebagai konversi tinju diikuti dengan konversi referensi eksplisit. Pada run-time, jikaT
merupakan jenis referensi, konversi dijalankan sebagai konversi referensi eksplisit. - Dari parameter
U
jenis hinggaT
yang disediakan tergantungT
padaU
(§15.2.5). Pada run-time, jikaT
adalah jenis nilai danU
merupakan jenis referensi, konversi dijalankan sebagai konversi unboxing. Pada run-time, jika danT
U
merupakan jenis nilai, makaT
danU
harus jenis yang sama dan tidak ada konversi yang dilakukan. Pada run-time, jikaT
merupakan jenis referensi, makaU
tentu juga merupakan jenis referensi dan konversi dijalankan sebagai konversi referensi eksplisit atau konversi identitas.
Dalam semua kasus, aturan memastikan bahwa konversi dijalankan sebagai konversi unboxing jika dan hanya jika pada run-time konversi berasal dari jenis referensi ke jenis nilai.
Aturan di atas tidak mengizinkan konversi eksplisit langsung dari parameter jenis yang tidak dibatasi ke jenis non-antarmuka, yang mungkin mengejutkan. Alasan untuk aturan ini adalah untuk mencegah kebingungan dan membuat semantik konversi tersebut jelas.
Contoh: Pertimbangkan deklarasi berikut:
class X<T> { public static long F(T t) { return (long)t; // Error } }
Jika konversi eksplisit langsung dari
t
kelong
diizinkan, seseorang mungkin dengan mudah mengharapkan ituX<int>.F(7)
akan mengembalikan7L
. Namun, itu tidak akan, karena konversi numerik standar hanya dipertimbangkan ketika jenis diketahui numerik pada waktu pengikatan. Untuk memperjelas semantik, contoh di atas harus ditulis:class X<T> { public static long F(T t) { return (long)(object)t; // Ok, but will only work when T is long } }
Kode ini sekarang akan dikompilasi tetapi mengeksekusi
X<int>.F(7)
kemudian akan melemparkan pengecualian pada run-time, karena kotak tidak dapat dikonversiint
langsung kelong
.contoh akhir
10.3.9 Konversi eksplisit yang ditentukan pengguna
Konversi eksplisit yang ditentukan pengguna terdiri dari konversi eksplisit standar opsional, diikuti dengan eksekusi operator konversi implisit atau eksplisit yang ditentukan pengguna, diikuti oleh konversi eksplisit standar opsional lainnya. Aturan yang tepat untuk mengevaluasi konversi eksplisit yang ditentukan pengguna dijelaskan dalam §10.5.5.
10.4 Konversi standar
10.4.1 Umum
Konversi standar adalah konversi yang telah ditentukan sebelumnya yang dapat terjadi sebagai bagian dari konversi yang ditentukan pengguna.
10.4.2 Konversi implisit Standar
Konversi implisit berikut diklasifikasikan sebagai konversi implisit standar:
- Konversi identitas (§10.2.2)
- Konversi numerik implisit (§10.2.3)
- Konversi implisit nullable (§10.2.6)
- Konversi harfiah null (§10.2.7)
- Konversi referensi implisit (§10.2.8)
- Konversi tinju (§10.2.9)
- Konversi ekspresi konstanta implisit (§10.2.11)
- Konversi implisit yang melibatkan parameter jenis (§10.2.12)
Konversi implisit standar secara khusus mengecualikan konversi implisit yang ditentukan pengguna.
10.4.3 Konversi eksplisit Standar
Konversi eksplisit standar adalah semua konversi implisit standar ditambah subset konversi eksplisit di mana konversi implisit standar yang berlawanan ada.
Catatan: Dengan kata lain, jika konversi implisit standar ada dari jenis
A
ke jenisB
, maka konversi eksplisit standar ada dari jenisA
ke jenisB
dan dari jenis ke jenisB
A
. catatan akhir
10.5 Konversi yang ditentukan pengguna
10.5.1 Umum
C# memungkinkan konversi implisit dan eksplisit yang telah ditentukan sebelumnya untuk ditambah oleh konversi yang ditentukan pengguna. Konversi yang ditentukan pengguna diperkenalkan dengan mendeklarasikan operator konversi (§15.10.4) di kelas dan jenis struktur.
10.5.2 Konversi yang ditentukan pengguna yang diizinkan
C# hanya mengizinkan konversi tertentu yang ditentukan pengguna untuk dideklarasikan. Secara khusus, tidak mungkin untuk menentukan ulang konversi implisit atau eksplisit yang sudah ada.
Untuk jenis S
sumber dan jenis T
target tertentu , jika S
atau T
jenis nilai nullable, biarkan S₀
dan T₀
lihat jenis yang mendasarnya, jika tidak S₀
dan T₀
sama dengan S
dan T
masing-masing. Kelas atau struktur diizinkan untuk mendeklarasikan konversi dari jenis sumber ke jenis S
T
target hanya jika semua hal berikut ini benar:
-
S₀
danT₀
merupakan jenis yang berbeda. - Baik
S₀
atauT₀
adalah kelas atau jenis struct tempat deklarasi operator berlangsung. - Tidak
S₀
jugaT₀
bukan interface_type. - Tidak termasuk konversi yang ditentukan pengguna, konversi tidak ada dari
S
keT
atau dariT
keS
.
Pembatasan yang berlaku untuk konversi yang ditentukan pengguna ditentukan dalam §15.10.4.
10.5.3 Evaluasi konversi yang ditentukan pengguna
Konversi yang ditentukan pengguna mengonversi ekspresi sumber, yang mungkin memiliki jenis sumber, ke jenis lain, yang disebut jenis target. Evaluasi pusat konversi yang ditentukan pengguna pada menemukan operator konversi yang ditentukan pengguna yang paling spesifik untuk ekspresi sumber dan jenis target. Penentuan ini dipecah menjadi beberapa langkah:
- Menemukan set kelas dan struktur tempat operator konversi yang ditentukan pengguna akan dipertimbangkan. Set ini terdiri dari jenis sumber dan kelas dasarnya, jika jenis sumber ada, bersama dengan jenis target dan kelas dasarnya. Untuk tujuan ini diasumsikan bahwa hanya kelas dan struktur yang dapat mendeklarasikan operator yang ditentukan pengguna, dan bahwa jenis non-kelas tidak memiliki kelas dasar. Selain itu, jika jenis sumber atau target adalah jenis nilai nullable, jenis yang mendasarnya digunakan sebagai gantinya.
- Dari kumpulan jenis tersebut, menentukan operator konversi yang ditentukan pengguna dan diangkat mana yang berlaku. Agar operator konversi berlaku, dimungkinkan untuk melakukan konversi standar (§10,4) dari ekspresi sumber ke jenis operand operator, dan dimungkinkan untuk melakukan konversi standar dari jenis hasil operator ke jenis target.
- Dari set operator yang ditentukan pengguna yang berlaku, menentukan operator mana yang tidak ambigu yang paling spesifik. Secara umum, operator yang paling spesifik adalah operator yang jenis operand-nya "paling dekat" dengan ekspresi sumber dan yang jenis hasilnya "paling dekat" dengan jenis target. Operator konversi yang ditentukan pengguna lebih disukai daripada operator konversi yang diangkat. Aturan yang tepat untuk menetapkan operator konversi yang ditentukan pengguna yang paling spesifik ditentukan ditentukan dalam subklaus berikut.
Setelah operator konversi yang ditentukan pengguna yang paling spesifik diidentifikasi, eksekusi aktual konversi yang ditentukan pengguna melibatkan hingga tiga langkah:
- Pertama, jika diperlukan, lakukan konversi standar dari ekspresi sumber ke jenis operand operator konversi yang ditentukan pengguna atau diangkat.
- Selanjutnya, panggil operator konversi yang ditentukan pengguna atau diangkat untuk melakukan konversi.
- Terakhir, jika diperlukan, melakukan konversi standar dari jenis hasil operator konversi yang ditentukan pengguna ke jenis target.
Evaluasi konversi yang ditentukan pengguna tidak pernah melibatkan lebih dari satu operator konversi yang ditentukan pengguna atau diangkat. Dengan kata lain, konversi dari jenis ke jenis S
T
tidak akan pernah terlebih dahulu menjalankan konversi yang ditentukan pengguna dari S
ke X
lalu menjalankan konversi yang ditentukan pengguna dari X
ke T
.
- Definisi yang tepat tentang evaluasi konversi implisit atau eksplisit yang ditentukan pengguna diberikan dalam subklaus berikut. Definisi menggunakan istilah-istilah berikut:
- Jika konversi implisit standar (§10.4.2) ada dari jenis
A
ke jenisB
, dan jika baikA
maupunB
bukan interface_type, makaA
dianggap termasuk dalamB
, danB
dianggap mencakupA
. - Jika konversi implisit standar (§10,4,2) ada dari ekspresi
E
ke jenisB
, dan jika tidakB
atau jenisE
(jika memilikinya) interface_type, kemudianE
dikatakan dilirik olehB
, danB
dikatakan kepada mencakupE
. - Jenis yang paling mencakup dalam sekumpulan jenis adalah satu jenis yang mencakup semua jenis lain dalam set. Jika tidak ada jenis tunggal yang mencakup semua jenis lainnya, maka set tidak memiliki jenis yang paling mencakup. Dalam istilah yang lebih intuitif, jenis yang paling mencakup adalah jenis "terbesar" dalam set —satu jenis yang masing-masing jenisnya dapat dikonversi secara implisit.
- Jenis yang paling mencakup dalam sekumpulan jenis adalah satu jenis yang disertakan oleh semua jenis lain dalam set. Jika tidak ada jenis tunggal yang dililit oleh semua jenis lainnya, maka set tidak memiliki jenis yang paling dilirik. Dalam istilah yang lebih intuitif, jenis yang paling mencakup adalah jenis "terkecil" dalam set —satu jenis yang dapat dikonversi secara implisit ke masing-masing jenis lainnya.
10.5.4 Konversi implisit yang ditentukan pengguna
Konversi implisit yang ditentukan pengguna dari ekspresi E
ke jenis T
diproses sebagai berikut:
Tentukan jenis
S
,S₀
danT₀
.- Jika
E
memiliki jenis, biarkanS
jenis tersebut. - Jika
S
atauT
adalah jenis nilai nullable, biarkanSᵢ
danTᵢ
menjadi jenis yang mendasarnya, jika tidak, biarkanSᵢ
danTᵢ
S
T
, masing-masing. - Jika
Sᵢ
atauTᵢ
merupakan parameter jenis, biarkanS₀
danT₀
jadilah kelas dasar yang efektif, jika tidak, biarkanS₀
danT₀
Sₓ
Tᵢ
, masing-masing.
- Jika
Temukan sekumpulan jenis,
D
, tempat operator konversi yang ditentukan pengguna akan dipertimbangkan. Set ini terdiri dariS₀
(jikaS₀
ada dan merupakan kelas atau struktur), kelasS₀
dasar (jikaS₀
ada dan merupakan kelas), danT₀
(jikaT₀
adalah kelas atau struktur). Jenis ditambahkan ke setD
hanya jika konversi identitas ke jenis lain yang sudah disertakan dalam set tidak ada.Temukan kumpulan operator konversi yang ditentukan pengguna dan diangkat yang berlaku,
U
. Set ini terdiri dari operator konversi implisit yang ditentukan pengguna dan diangkat yang dideklarasikan oleh kelas atau struktur dalamD
konversi tersebut dari jenis yang mencakupE
ke jenis yang dicakup olehT
. JikaU
kosong, konversi tidak terdefinisi dan terjadi kesalahan waktu kompilasi.- Jika
S
ada dan salah satu operator dalamU
konversi dariS
, makaSₓ
adalahS
. - Jika tidak,
Sₓ
adalah jenis yang paling mencakup dalam kumpulan gabungan jenis sumber operator diU
. Jika tepat satu jenis yang paling lengkap tidak dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi.
- Jika
Temukan jenis target yang paling spesifik,
Tₓ
, dari operator diU
:- Jika salah satu operator dalam
U
konversi keT
, makaTₓ
adalahT
. - Jika tidak,
Tₓ
adalah jenis yang paling mencakup dalam kumpulan gabungan jenis target operator diU
. Jika tepat satu jenis yang paling mencakup tidak dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi.
- Jika salah satu operator dalam
Temukan operator konversi yang paling spesifik:
- Jika
U
berisi tepat satu operator konversi yang ditentukan pengguna yang dikonversi dariSₓ
keTₓ
, maka ini adalah operator konversi yang paling spesifik. - Jika tidak, jika
U
berisi tepat satu operator konversi yang diangkat yang dikonversi dariSₓ
keTₓ
, maka ini adalah operator konversi yang paling spesifik. - Jika tidak, konversi bersifat ambigu dan terjadi kesalahan waktu kompilasi.
- Jika
Terakhir, terapkan konversi:
- Jika E belum memiliki jenis
Sₓ
, maka konversi implisit standar dariE
keSₓ
dilakukan. - Operator konversi yang paling spesifik dipanggil untuk mengonversi dari
Sₓ
keTₓ
. - Jika
Tₓ
tidakT
, maka konversi implisit standar dariTₓ
keT
dilakukan.
- Jika E belum memiliki jenis
Konversi implisit yang ditentukan pengguna dari jenis S
ke jenis T
ada jika konversi implisit yang ditentukan pengguna ada dari variabel jenis S
ke T
.
10.5.5 Konversi eksplisit yang ditentukan pengguna
Konversi eksplisit yang ditentukan pengguna dari ekspresi E
ke jenis T
diproses sebagai berikut:
- Tentukan jenis
S
,S₀
danT₀
.- Jika
E
memiliki jenis, biarkanS
jenis tersebut. - Jika
S
atauT
adalah jenis nilai nullable, biarkanSᵢ
danTᵢ
menjadi jenis yang mendasarnya, jika tidak, biarkanSᵢ
danTᵢ
S
T
, masing-masing. - Jika
Sᵢ
atauTᵢ
merupakan parameter jenis, biarkanS₀
danT₀
jadilah kelas dasar yang efektif, jika tidak, biarkanS₀
danT₀
Sᵢ
Tᵢ
, masing-masing.
- Jika
- Temukan sekumpulan jenis,
D
, tempat operator konversi yang ditentukan pengguna akan dipertimbangkan. Set ini terdiri dariS₀
(jikaS₀
ada dan merupakan kelas atau struktur), kelasS₀
dasar (jikaS₀
ada dan merupakan kelas),T₀
(jikaT₀
adalah kelas atau struct), dan kelasT₀
dasar (jikaT₀
adalah kelas). Jenis ditambahkan ke setD
hanya jika konversi identitas ke jenis lain yang sudah disertakan dalam set tidak ada. - Temukan kumpulan operator konversi yang ditentukan pengguna dan diangkat yang berlaku,
U
. Set ini terdiri dari operator konversi implisit atau eksplisit yang ditentukan pengguna dan diangkat yang dideklarasikan oleh kelas atau struktur dalamD
konversi tersebut dari jenis yang mencakupE
atau dicakup olehS
(jika ada) ke jenis yang mencakup atau dicakup olehT
. JikaU
kosong, konversi tidak terdefinisi dan terjadi kesalahan waktu kompilasi. - Temukan jenis sumber yang paling spesifik,
Sₓ
, dari operator diU
:- Jika S ada dan salah satu operator dalam
U
konversi dariS
, makaSₓ
adalahS
. - Jika tidak, jika salah satu operator dalam
U
konversi dari jenis yang mencakupE
, makaSₓ
adalah jenis yang paling terpusat dalam kumpulan gabungan jenis sumber operator tersebut. Jika tidak ada jenis yang paling lengkap yang dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi. - Jika tidak,
Sₓ
adalah jenis yang paling mencakup dalam kumpulan gabungan jenis sumber operator diU
. Jika tepat satu jenis yang paling mencakup tidak dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi.
- Jika S ada dan salah satu operator dalam
- Temukan jenis target yang paling spesifik,
Tₓ
, dari operator diU
:- Jika salah satu operator dalam
U
konversi keT
, makaTₓ
adalahT
. - Jika tidak, jika salah satu operator dalam
U
konversi ke jenis yang disertakan olehT
, makaTₓ
adalah jenis yang paling mencakup dalam kumpulan gabungan jenis target operator tersebut. Jika tepat satu jenis yang paling mencakup tidak dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi. - Jika tidak,
Tₓ
adalah jenis yang paling mencakup dalam kumpulan gabungan jenis target operator diU
. Jika tidak ada jenis yang paling lengkap yang dapat ditemukan, maka konversi ambigu dan terjadi kesalahan waktu kompilasi.
- Jika salah satu operator dalam
- Temukan operator konversi yang paling spesifik:
- Jika U berisi tepat satu operator konversi yang ditentukan pengguna yang dikonversi dari
Sₓ
keTₓ
, maka ini adalah operator konversi yang paling spesifik. - Jika tidak, jika
U
berisi tepat satu operator konversi yang diangkat yang dikonversi dariSₓ
keTₓ
, maka ini adalah operator konversi yang paling spesifik. - Jika tidak, konversi bersifat ambigu dan terjadi kesalahan waktu kompilasi.
- Jika U berisi tepat satu operator konversi yang ditentukan pengguna yang dikonversi dari
- Terakhir, terapkan konversi:
- Jika
E
belum memiliki jenisSₓ
, maka konversi eksplisit standar dari E keSₓ
dilakukan. - Operator konversi yang ditentukan pengguna yang paling spesifik dipanggil untuk mengonversi dari
Sₓ
keTₓ
. - Jika
Tₓ
tidakT
, maka konversi eksplisit standar dariTₓ
keT
dilakukan.
- Jika
Konversi eksplisit yang ditentukan pengguna dari jenis S
ke jenis T
ada jika konversi eksplisit yang ditentukan pengguna ada dari variabel jenis S
ke T
.
10.6 Konversi yang melibatkan jenis nullable
10.6.1 Konversi Nullable
Konversi nullable mengizinkan konversi yang telah ditentukan sebelumnya yang beroperasi pada jenis nilai yang tidak dapat diubah ke null untuk juga digunakan dengan bentuk nullable dari jenis tersebut. Untuk setiap konversi implisit atau eksplisit yang telah ditentukan sebelumnya yang mengonversi dari jenis nilai yang tidak dapat diubah ke jenis S
T
nilai yang tidak dapat diubah ke null (§10.2.2, §10.2.3, §10.2.4, §10.2.11, §10.3.2 dan §10.3.3), konversi nullable berikut ada:
- Konversi implisit atau eksplisit dari
S?
keT?
- Konversi implisit atau eksplisit dari
S
keT?
- Konversi eksplisit dari
S?
keT
.
Konversi nullable itu sendiri diklasifikasikan sebagai konversi implisit atau eksplisit.
Konversi nullable tertentu diklasifikasikan sebagai konversi standar dan dapat terjadi sebagai bagian dari konversi yang ditentukan pengguna. Secara khusus, semua konversi nullable implisit diklasifikasikan sebagai konversi implisit standar (§10.4.2), dan konversi eksplisit nullable yang memenuhi persyaratan §10.4.3 diklasifikasikan sebagai konversi eksplisit standar.
Evaluasi konversi nullable berdasarkan konversi yang mendasar dari S
ke T
melanjutkan sebagai berikut:
- Jika konversi nullable adalah dari
S?
keT?
:- Jika nilai sumber null (
HasValue
properti adalahfalse
), hasilnya adalah nilai null dari jenisT?
. - Jika tidak, konversi dievaluasi sebagai pembungkusan dari
S?
keS
, diikuti oleh konversi yang mendasar dariS
keT
, diikuti dengan pembungkusan dariT
keT?
.
- Jika nilai sumber null (
- Jika konversi nullable adalah dari
S
keT?
, konversi dievaluasi sebagai konversi yang mendasar dariS
menjadiT
diikuti dengan pembungkusan dariT
keT?
. - Jika konversi nullable adalah dari
S?
keT
, konversi dievaluasi sebagai unwrapping dariS?
keS
diikuti dengan konversi yang mendasar dariS
keT
.
10.6.2 Konversi yang diangkat
Mengingat operator konversi yang ditentukan pengguna yang mengonversi dari jenis nilai yang tidak dapat diubah ke jenis S
nilai yang tidak dapat diubah ke null, T
konversi yang diangkat ada yang mengonversi dari ke S?
.T?
Operator konversi yang diangkat ini melakukan pembungkusan dari S?
ke S
diikuti oleh konversi yang ditentukan pengguna dari S
ke T
diikuti dengan pembungkusan dari T
ke T?
, kecuali bahwa nilai S?
null dikonversi langsung ke nilai T?
null . Operator konversi yang diangkat memiliki klasifikasi implisit atau eksplisit yang sama dengan operator konversi yang mendasar yang ditentukan pengguna.
10.7 Konversi fungsi anonim
10.7.1 Umum
anonymous_method_expression atau lambda_expression diklasifikasikan sebagai fungsi anonim (§12.19). Ekspresi tidak memiliki jenis, tetapi dapat dikonversi secara implisit ke jenis delegasi yang kompatibel. Beberapa ekspresi lambda juga dapat dikonversi secara implisit ke jenis pohon ekspresi yang kompatibel.
Secara khusus, fungsi F
anonim kompatibel dengan jenis D
delegasi yang disediakan:
- Jika
F
berisi anonymous_function_signature, makaD
danF
memiliki jumlah parameter yang sama. - Jika
F
tidak berisi anonymous_function_signature, makaD
mungkin memiliki parameter nol atau lebih dari jenis apa pun, selama tidak ada parameterD
yang merupakan parameter output. - Jika
F
memiliki daftar parameter yang ditik secara eksplisit, setiap parameter diD
memiliki pengubah yang sama dengan parameter yang sesuai di dan konversi identitas ada diF
antara parameter yang sesuai diF
. - Jika
F
memiliki daftar parameter yang ditik secara implisit,D
tidak memiliki parameter referensi atau output. - Jika isi
F
adalah ekspresi , danD
memiliki jenis pengembalian yang batal atauF
asinkron danD
memiliki«TaskType»
jenis pengembalian (§15.14.1), maka ketika setiap parameterF
diberikan jenis parameter yang sesuai diD
, isinyaF
adalah ekspresi yang valid (w.r.t §12) yang akan diizinkan sebagai statement_expression (§13.7). - Jika isi
F
adalah blok, danD
memiliki jenis pengembalian yang batal atauF
asinkron danD
memiliki«TaskType»
jenis pengembalian , maka ketika setiap parameterF
diberikan jenis parameter yang sesuai diD
, isinyaF
adalah blok yang valid (w.r.t §13.3) di mana tidak adareturn
pernyataan yang menentukan ekspresi. - Jika isi
F
adalah ekspresi, dan baikF
tidak asinkron danD
memiliki jenis pengembalian non-void
T
, atauF
asinkron danD
memiliki jenis pengembalian«TaskType»<T>
(§15.14.1), maka ketika setiap parameterF
diberi tipe yang sesuai dengan parameter diD
, isiF
adalah ekspresi yang valid (w.r.t §12) yang secara implisit dapat dikonversi keT
. - Jika isi
F
adalah blok, dan tidakF
asinkron danD
memiliki jenisT
pengembalian non-void , asinkron danF
memilikiD
jenis pengembalian, maka ketika setiap parameter«TaskType»<T>
diberikan jenis parameter yang sesuai diF
, isinyaD
adalah blok pernyataan yang valid (w.r.tF
) dengan titik akhir yang tidak dapat dijangkau di mana setiap pernyataan pengembalian menentukan ekspresi yang secara implisit dapat dikonversi ke .
Contoh: Contoh berikut mengilustrasikan aturan ini:
delegate void D(int x); D d1 = delegate { }; // Ok D d2 = delegate() { }; // Error, signature mismatch D d3 = delegate(long x) { }; // Error, signature mismatch D d4 = delegate(int x) { }; // Ok D d5 = delegate(int x) { return; }; // Ok D d6 = delegate(int x) { return x; }; // Error, return type mismatch delegate void E(out int x); E e1 = delegate { }; // Error, E has an output parameter E e2 = delegate(out int x) { x = 1; }; // Ok E e3 = delegate(ref int x) { x = 1; }; // Error, signature mismatch delegate int P(params int[] a); P p1 = delegate { }; // Error, end of block reachable P p2 = delegate { return; }; // Error, return type mismatch P p3 = delegate { return 1; }; // Ok P p4 = delegate { return "Hello"; }; // Error, return type mismatch P p5 = delegate(int[] a) // Ok { return a[0]; }; P p6 = delegate(params int[] a) // Error, params modifier { return a[0]; }; P p7 = delegate(int[] a) // Error, return type mismatch { if (a.Length > 0) return a[0]; return "Hello"; }; delegate object Q(params int[] a); Q q1 = delegate(int[] a) // Ok { if (a.Length > 0) return a[0]; return "Hello"; };
contoh akhir
Contoh: Contoh berikut menggunakan jenis
Func<A,R>
delegasi generik yang mewakili fungsi yang mengambil argumen jenisA
dan mengembalikan nilai jenisR
:delegate R Func<A,R>(A arg);
Dalam penugasan
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
parameter dan jenis pengembalian dari setiap fungsi anonim ditentukan dari jenis variabel tempat fungsi anonim ditetapkan.
Penugasan pertama berhasil mengonversi fungsi anonim ke jenis
Func<int,int>
delegasi karena, ketikax
diberikan jenisint
,x + 1
adalah ekspresi valid yang secara implisit dapat dikonversi ke jenisint
.Demikian juga, penetapan kedua berhasil mengonversi fungsi anonim ke jenis delegasi Func<int, ganda> karena hasil
x + 1
(dari jenisint
) secara implisit dapat dikonversi ke jenisdouble
.Namun, penugasan ketiga adalah kesalahan waktu kompilasi karena, ketika
x
diberikan jenisdouble
, hasilx + 1
(dari jenisdouble
) tidak secara implisit dapat dikonversi ke jenisint
.Penugasan keempat berhasil mengonversi fungsi asinkron anonim ke jenis
Func<int, Task<int>>
delegasi karena hasilx + 1
(dari jenisint
) secara implisit dapat dikonversi ke jenisint
pengembalian efektif dari asinkron lambda, yang memiliki jenisTask<int>
pengembalian .contoh akhir
Ekspresi F
lambda kompatibel dengan jenis Expression<D>
pohon ekspresi jika F
kompatibel dengan jenis D
delegasi . Ini tidak berlaku untuk metode anonim, hanya ekspresi lambda.
Fungsi anonim dapat memengaruhi resolusi kelebihan beban, dan berpartisipasi dalam inferensi jenis. Lihat §12.6 untuk detail lebih lanjut.
10.7.2 Evaluasi konversi fungsi anonim ke jenis delegasi
Konversi fungsi anonim ke jenis delegasi menghasilkan instans delegasi yang mereferensikan fungsi anonim dan set (mungkin kosong) dari variabel luar yang ditangkap yang aktif pada saat evaluasi. Ketika delegasi dipanggil, isi fungsi anonim dijalankan. Kode dalam isi dijalankan menggunakan sekumpulan variabel luar yang ditangkap yang direferensikan oleh delegasi. delegate_creation_expression (§12.8.17.5) dapat digunakan sebagai sintaks alternatif untuk mengonversi metode anonim ke jenis delegasi.
Daftar pemanggilan delegasi yang dihasilkan dari fungsi anonim berisi satu entri. Objek target yang tepat dan metode target delegasi tidak ditentukan. Secara khusus, tidak ditentukan apakah objek target delegasi adalah null
, this
nilai anggota fungsi penutup, atau beberapa objek lainnya.
Konversi fungsi anonim yang identik secara semantik dengan kumpulan instans variabel luar yang ditangkap (mungkin kosong) yang sama ke jenis delegasi yang sama diizinkan (tetapi tidak diperlukan) untuk mengembalikan instans delegasi yang sama. Istilah yang identik secara semantik digunakan di sini untuk berarti bahwa eksekusi fungsi anonim akan, dalam semua kasus, menghasilkan efek yang sama mengingat argumen yang sama. Aturan ini mengizinkan kode seperti berikut ini untuk dioptimalkan.
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));
...
}
}
Karena dua delegasi fungsi anonim memiliki kumpulan variabel luar yang ditangkap (kosong) yang sama, dan karena fungsi anonim secara semantik identik, kompilator diizinkan untuk meminta delegasi merujuk ke metode target yang sama. Kompilator diizinkan untuk mengembalikan instans delegasi yang sama persis dari kedua ekspresi fungsi anonim.
10.7.3 Evaluasi konversi ekspresi lambda ke jenis pohon ekspresi
Konversi ekspresi lambda ke jenis pohon ekspresi menghasilkan pohon ekspresi (§8,6). Lebih tepatnya, evaluasi konversi ekspresi lambda menghasilkan struktur objek yang mewakili struktur ekspresi lambda itu sendiri.
Tidak setiap ekspresi lambda dapat dikonversi ke jenis pohon ekspresi. Konversi ke jenis delegasi yang kompatibel selalu ada, tetapi mungkin gagal pada waktu kompilasi karena alasan yang ditentukan implementasi.
Catatan: Alasan umum untuk ekspresi lambda gagal dikonversi ke jenis pohon ekspresi meliputi:
- Ini memiliki badan blok
- Ini memiliki pengubah
async
- Ini berisi operator penugasan
- Ini berisi parameter output atau referensi
- Ini berisi ekspresi yang terikat secara dinamis
catatan akhir
10.8 Konversi grup metode
Konversi implisit ada dari grup metode (§12,2) ke jenis delegasi yang kompatibel (§20,4). Jika D
adalah jenis delegasi, dan E
merupakan ekspresi yang diklasifikasikan sebagai grup metode, maka D
kompatibel dengan E
jika dan hanya jika E
berisi setidaknya satu metode yang berlaku dalam bentuk normalnya (§12.6.4.2) ke daftar argumen apa pun (§12.6.2) memiliki jenis dan pengubah yang cocok dengan jenis parameter dan pengubah D
, seperti yang dijelaskan dalam hal berikut.
Aplikasi waktu kompilasi konversi dari grup E
metode ke jenis D
delegasi dijelaskan dalam hal berikut.
- Metode tunggal
M
dipilih sesuai dengan pemanggilan metode (§12.8.10.2) formulirE(A)
, dengan modifikasi berikut:- Daftar
A
argumen adalah daftar ekspresi, masing-masing diklasifikasikan sebagai variabel dan dengan jenis dan pengubah (in
,out
, atauref
) dari parameter yang sesuai dalam — kecuali parameter jenisD
, di mana ekspresi yang sesuai memiliki jenisdynamic
alih-alihobject
. - Metode kandidat yang dipertimbangkan hanya metode yang berlaku dalam bentuk normalnya dan tidak menghilangkan parameter opsional apa pun (§12.6.4.2). Dengan demikian, metode kandidat diabaikan jika hanya berlaku dalam bentuk yang diperluas, atau jika satu atau beberapa parameter opsional mereka tidak memiliki parameter yang sesuai di
D
.
- Daftar
- Konversi dianggap ada jika algoritma §12.8.10.2
- Jika metode
M
yang dipilih adalah metode instans, ekspresi instans yang terkait denganE
menentukan objek target delegasi. - Jika metode
M
yang dipilih adalah metode ekstensi yang ditandai dengan akses anggota pada ekspresi instans, ekspresi instans tersebut menentukan objek target delegasi. - Hasil konversi adalah nilai jenis
D
, yaitu delegasi yang mengacu pada metode yang dipilih dan objek target.
Contoh: Berikut ini menunjukkan konversi grup metode:
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 } }
Penugasan untuk
d1
secara implisit mengonversi grupF
metode menjadi nilai jenisD1
.Penugasan untuk
d2
menunjukkan bagaimana mungkin untuk membuat delegasi ke metode yang memiliki jenis parameter yang kurang diturunkan (kontravarian) dan jenis pengembalian yang lebih turunan (kovarian).Penugasan untuk
d3
menunjukkan bagaimana tidak ada konversi jika metode tidak berlaku.Penugasan untuk
d4
menunjukkan bagaimana metode harus berlaku dalam bentuk normalnya.Penugasan untuk
d5
menunjukkan bagaimana parameter dan jenis pengembalian delegasi dan metode diizinkan untuk berbeda hanya untuk jenis referensi.contoh akhir
Seperti halnya semua konversi implisit dan eksplisit lainnya, operator cast dapat digunakan untuk melakukan konversi tertentu secara eksplisit.
Contoh: Dengan demikian, contoh
object obj = new EventHandler(myDialog.OkClick);
dapat ditulis sebagai gantinya
object obj = (EventHandler)myDialog.OkClick;
contoh akhir
Konversi grup metode dapat merujuk ke metode generik, baik dengan secara eksplisit menentukan argumen jenis dalam E
, atau melalui inferensi jenis (§12.6.3). Jika inferensi jenis digunakan, jenis parameter delegasi digunakan sebagai jenis argumen dalam proses inferensi. Jenis pengembalian delegasi tidak digunakan untuk inferensi. Apakah argumen jenis ditentukan atau disimpulkan, argumen tersebut adalah bagian dari proses konversi grup metode; ini adalah argumen jenis yang digunakan untuk memanggil metode target ketika delegasi yang dihasilkan dipanggil.
Contoh:
delegate int D(string s, int i); delegate int E(); class X { public static T F<T>(string s, T t) {...} public static T G<T>() {...} static void Main() { D d1 = F<int>; // Ok, type argument given explicitly D d2 = F; // Ok, int inferred as type argument E e1 = G<int>; // Ok, type argument given explicitly E e2 = G; // Error, cannot infer from return type } }
contoh akhir
Grup metode dapat memengaruhi resolusi kelebihan beban, dan berpartisipasi dalam inferensi jenis. Lihat §12.6 untuk detail lebih lanjut.
Evaluasi run-time dari konversi grup metode berlanjut sebagai berikut:
- Jika metode yang dipilih pada waktu kompilasi adalah metode instans, atau merupakan metode ekstensi yang diakses sebagai metode instans, objek target delegasi ditentukan dari ekspresi instans yang terkait dengan
E
:- Ekspresi instans dievaluasi. Jika evaluasi ini menyebabkan pengecualian, tidak ada langkah lebih lanjut yang dijalankan.
- Jika ekspresi instans adalah reference_type, nilai yang dihitung oleh ekspresi instans menjadi objek target. Jika metode yang dipilih adalah metode instans dan objek target adalah
null
,System.NullReferenceException
akan dilemparkan dan tidak ada langkah lebih lanjut yang dijalankan. - Jika ekspresi instans adalah value_type, operasi tinju (§10.2.9) dilakukan untuk mengonversi nilai menjadi objek, dan objek ini menjadi objek target.
- Jika tidak, metode yang dipilih adalah bagian dari panggilan metode statis, dan objek target delegasi adalah
null
. - Instans delegasi jenis
D
delegasi diperoleh dengan referensi ke metode yang ditentukan pada waktu kompilasi dan referensi ke objek target yang dihitung di atas, sebagai berikut:- Konversi diizinkan (tetapi tidak diperlukan) untuk menggunakan instans delegasi yang ada yang sudah berisi referensi ini.
- Jika instans yang ada tidak digunakan kembali, instans baru dibuat (§20,5). Jika tidak ada cukup memori yang tersedia untuk mengalokasikan instans baru, akan
System.OutOfMemoryException
dilemparkan. Jika tidak, instans diinisialisasi dengan referensi yang diberikan.
ECMA C# draft specification