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.
Dalam praktiknya, aturan untuk menentukan resolusi kelebihan beban dimaksudkan untuk menemukan kelebihan beban yang "paling dekat" dengan argumen aktual yang disediakan. Jika ada metode yang jenis parameternya cocok dengan jenis argumen, maka metode tersebut jelas yang paling dekat. Melarangnya, satu metode lebih dekat dari metode lain jika semua jenis parameternya lebih sempit daripada (atau sama dengan) jenis parameter metode lainnya. Jika tidak ada parameter metode yang lebih sempit dari yang lain, maka tidak ada cara untuk menentukan metode mana yang lebih dekat dengan argumen.
Nota. Resolusi kelebihan beban tidak memperhitungkan jenis pengembalian metode yang diharapkan.
Perhatikan juga bahwa karena sintaks parameter bernama, pengurutan parameter aktual dan formal mungkin tidak sama.
Mengingat grup metode, metode yang paling berlaku dalam grup untuk daftar argumen ditentukan menggunakan langkah-langkah berikut. Jika, setelah menerapkan langkah tertentu, tidak ada anggota yang tetap berada dalam set, maka kesalahan waktu kompilasi terjadi. Jika hanya satu anggota yang tetap berada di set, maka anggota tersebut adalah anggota yang paling berlaku. Langkah-langkahnya adalah:
Pertama, jika tidak ada argumen jenis yang disediakan, terapkan inferensi jenis ke metode apa pun yang memiliki parameter jenis. Jika inferensi jenis berhasil untuk metode, maka argumen jenis yang disimpulkan digunakan untuk metode tertentu. Jika inferensi jenis gagal untuk metode, maka metode tersebut dihilangkan dari set.
Selanjutnya, hilangkan semua anggota dari set yang tidak dapat diakses atau tidak berlaku (Bagian Penerapan Ke Daftar Argumen) ke daftar argumen
Selanjutnya, jika satu atau beberapa argumen adalah
AddressOfatau ekspresi lambda, maka hitung tingkat relaksasi delegasi untuk setiap argumen seperti di bawah ini. Jika tingkat relaksasi delegasi terburuk (terendah) masukNlebih buruk daripada tingkat relaksasi delegasi terendah diM, maka hilangkanNdari set. Tingkat relaksasi delegasi adalah sebagai berikut:Kesalahan mendelegasikan tingkat relaksasi -- jika
AddressOfatau lambda tidak dapat dikonversi ke jenis delegasi.Mempersempit relaksasi jenis pengembalian atau parameter -- jika argumen adalah
AddressOfatau lambda dengan jenis yang dinyatakan dan konversi dari jenis pengembaliannya ke jenis pengembalian delegasi menyempit; atau jika argumen adalah lambda biasa dan konversi dari salah satu ekspresi pengembaliannya ke jenis pengembalian delegasi menyempit, atau jika argumen adalah lambda asinkron dan jenis pengembalian delegasi adalahTask(Of T)dan konversi dari salah satu ekspresiTpengembaliannya menjadi menyempit; atau jika argumen adalah lambda iterator dan jenisIEnumerator(Of T)pengembalian delegasi atauIEnumerable(Of T)dan konversi dari salah satu operan hasilnya menjadiTmenyempit.Pelesiran mendelegasikan relaksasi untuk mendelegasikan tanpa tanda tangan -- jika jenis delegasi adalah
System.DelegateatauSystem.MultiCastDelegateatauSystem.Object.Drop return atau argumen mendelegasikan relaksasi -- jika argumen adalah
AddressOfatau lambda dengan jenis pengembalian yang dinyatakan dan jenis delegasi tidak memiliki jenis pengembalian; atau jika argumen adalah lambda dengan satu atau beberapa ekspresi pengembalian dan jenis delegasi tidak memiliki jenis pengembalian; atau jika argumen adalahAddressOfatau lambda tanpa parameter dan jenis delegasi memiliki parameter.Memperlebar relaksasi delegasi jenis pengembalian -- jika argumen adalah
AddressOfatau lambda dengan jenis pengembalian yang dinyatakan, dan ada konversi yang melebar dari jenis pengembaliannya ke delegasi; atau jika argumen adalah lambda reguler di mana konversi dari semua ekspresi pengembalian ke jenis pengembalian delegasi melebar atau identitas dengan setidaknya satu pelesiran; atau jika argumen adalah lambda asinkron dan delegasi adalahTask(Of T)atauTaskdan konversi dari semua ekspresi pengembalian keT/Objectmasing-masing melebar atau identitas dengan setidaknya satu pelesiran; atau jika argumen adalah lambda iterator dan delegasi adalahIEnumerator(Of T)atau atauIEnumerable(Of T)atauIEnumeratorIEnumerabledan konversi dari semua ekspresi pengembalian menjadiT/Objectmelebar atau identitas dengan setidaknya satu pellebaran.Relaksasi delegasi identitas -- jika argumen adalah
AddressOfatau lambda yang cocok dengan delegasi dengan tepat, tanpa pelebaran atau penyempitan atau penurunan parameter atau pengembalian atau hasil. Selanjutnya, jika beberapa anggota set tidak mengharuskan konversi yang dipersempit berlaku untuk salah satu argumen, maka hilangkan semua anggota yang melakukannya. Contohnya:
Sub f(x As Object) End Sub Sub f(x As Short) End Sub Sub f(x As Short()) End Sub f("5") ' picks the Object overload, since String->Short is narrowing f(5) ' picks the Object overload, since Integer->Short is narrowing f({5}) ' picks the Object overload, since Integer->Short is narrowing f({}) ' a tie-breaker rule subsequent to [3] picks the Short() overloadSelanjutnya, eliminasi dilakukan berdasarkan penyempitan sebagai berikut. (Perhatikan bahwa, jika Opsi Ketat Aktif, maka semua anggota yang memerlukan penyempitan telah dinilai tidak dapat diterapkan (Bagian Berlaku Untuk Daftar Argumen) dan dihapus oleh Langkah 2.)
- Jika beberapa anggota instans set hanya memerlukan konversi yang mempersempit di mana jenis ekspresi argumen adalah
Object, maka hilangkan semua anggota lain. - Jika set berisi lebih dari satu anggota yang hanya memerlukan penyempitan dari
Object, maka ekspresi target pemanggilan diklasifikasikan ulang sebagai akses metode terikat terlambat (dan kesalahan diberikan jika jenis yang berisi grup metode adalah antarmuka, atau jika salah satu anggota yang berlaku adalah anggota ekstensi). - Jika ada kandidat yang hanya memerlukan penyempitan dari literal numerik, maka pilih yang paling spesifik di antara semua kandidat yang tersisa dengan langkah-langkah di bawah ini. Jika pemenang hanya memerlukan penyempitan dari literal numerik, maka dipilih sebagai hasil dari resolusi kelebihan beban; jika tidak, itu adalah kesalahan.
Nota. Pembenaran untuk aturan ini adalah bahwa jika program diketik secara longgar (yaitu, sebagian besar atau semua variabel dinyatakan sebagai
Object), resolusi kelebihan beban bisa sulit ketika banyak konversi dariObjectpenyempitan. Daripada resolusi kelebihan beban gagal dalam banyak situasi (membutuhkan pengetikan argumen yang kuat ke panggilan metode), resolusi metode kelebihan beban yang sesuai untuk panggilan ditangguhkan sampai run time. Ini memungkinkan panggilan yang diketik secara longgar berhasil tanpa cast tambahan. Efek samping yang tidak menguntungkan dari ini, bagaimanapun, adalah bahwa melakukan panggilan terlambat terikat memerlukan transmisi target panggilan keObject. Dalam kasus nilai struktur, ini berarti bahwa nilai harus dikotak ke sementara. Jika metode akhirnya disebut mencoba mengubah bidang struktur, perubahan ini akan hilang setelah metode kembali. Antarmuka dikecualikan dari aturan khusus ini karena pengikatan terlambat selalu diselesaikan terhadap anggota kelas runtime atau jenis struktur, yang mungkin memiliki nama yang berbeda dari anggota antarmuka yang mereka terapkan.- Jika beberapa anggota instans set hanya memerlukan konversi yang mempersempit di mana jenis ekspresi argumen adalah
Selanjutnya, jika ada metode instans yang tetap dalam set yang tidak memerlukan penyempitan, maka hilangkan semua metode ekstensi dari set. Contohnya:
Imports System.Runtime.CompilerServices Class C3 Sub M1(d As Integer) End Sub End Class Module C3Extensions <Extension> _ Sub M1(c3 As C3, c As Long) End Sub <Extension> _ Sub M1(c3 As C3, c As Short) End Sub End Module Module Test Sub Main() Dim c As New C3() Dim sVal As Short = 10 Dim lVal As Long = 20 ' Calls C3.M1, since C3.M1 is applicable. c.M1(sVal) ' Calls C3Extensions.M1 since C3.M1 requires a narrowing conversion c.M1(lVal) End Sub End ModuleNota. Metode ekstensi diabaikan jika ada metode instans yang berlaku untuk menjamin bahwa menambahkan impor (yang mungkin membawa metode ekstensi baru ke dalam cakupan) tidak akan menyebabkan panggilan pada metode instans yang ada untuk diikat ulang ke metode ekstensi. Mengingat cakupan luas dari beberapa metode ekstensi (yaitu yang ditentukan pada antarmuka dan/atau parameter jenis), ini adalah pendekatan yang lebih aman untuk mengikat metode ekstensi.
Selanjutnya, jika, mengingat dua anggota set
MdanN,Mlebih spesifik ( Kekhususan Bagian anggota/jenis diberikan daftar argumen) daripadaNyang diberikan daftar argumen, hilangkanNdari set. Jika lebih dari satu anggota tetap dalam set dan anggota yang tersisa tidak sama spesifiknya mengingat daftar argumen, hasil kesalahan waktu kompilasi.Jika tidak, mengingat dua anggota set,
MdanN, terapkan aturan pemecahan ikatan berikut, secara berurutan:Jika
Mtidak memiliki parameter ParamArray tetapiNtidak, atau jika keduanya melakukannya tetapiMmeneruskan lebih sedikit argumen ke parameter ParamArray daripadaNyang dilakukan, maka hilangkanNdari set. Contohnya:Module Test Sub F(a As Object, ParamArray b As Object()) Console.WriteLine("F(Object, Object())") End Sub Sub F(a As Object, b As Object, ParamArray c As Object()) Console.WriteLine("F(Object, Object, Object())") End Sub Sub G(Optional a As Object = Nothing) Console.WriteLine("G(Object)") End Sub Sub G(ParamArray a As Object()) Console.WriteLine("G(Object())") End Sub Sub Main() F(1) F(1, 2) F(1, 2, 3) G() End Sub End ModuleContoh di atas menghasilkan output berikut:
F(Object, Object()) F(Object, Object, Object()) F(Object, Object, Object()) G(Object)Nota. Ketika kelas mendeklarasikan metode dengan parameter paramarray, tidak jarang juga menyertakan beberapa bentuk yang diperluas sebagai metode reguler. Dengan demikian, dimungkinkan untuk menghindari alokasi instans array yang terjadi ketika bentuk metode yang diperluas dengan parameter paramarray dipanggil.
Jika
Mdidefinisikan dalam jenis yang lebih turunan daripadaN, hilangkanNdari set. Contohnya:Class Base Sub F(Of T, U)(x As T, y As U) End Sub End Class Class Derived Inherits Base Overloads Sub F(Of T, U)(x As U, y As T) End Sub End Class Module Test Sub Main() Dim d As New Derived() ' Calls Derived.F d.F(10, 10) End Sub End ModuleAturan ini juga berlaku untuk jenis yang didefinisikan oleh metode ekstensi. Contohnya:
Imports System.Runtime.CompilerServices Class Base End Class Class Derived Inherits Base End Class Module BaseExt <Extension> _ Sub M(b As Base, x As Integer) End Sub End Module Module DerivedExt <Extension> _ Sub M(d As Derived, x As Integer) End Sub End Module Module Test Sub Main() Dim b As New Base() Dim d As New Derived() ' Calls BaseExt.M b.M(10) ' Calls DerivedExt.M d.M(10) End Sub End ModuleJika
MdanNmerupakan metode ekstensi dan jenisMtarget adalah kelas atau struktur dan jenisNtarget adalah antarmuka, hilangkanNdari set. Contohnya:Imports System.Runtime.CompilerServices Interface I1 End Interface Class C1 Implements I1 End Class Module Ext1 <Extension> _ Sub M(i As I1, x As Integer) End Sub End Module Module Ext2 <Extension> _ Sub M(c As C1, y As Integer) End Sub End Module Module Test Sub Main() Dim c As New C1() ' Calls Ext2.M, because Ext1.M is hidden since it extends ' an interface. c.M(10) ' Calls Ext1.M CType(c, I1).M(10) End Sub End ModuleJika
MdanNmerupakan metode ekstensi, dan jenisMtarget danNidentik setelah penggantian parameter jenis, dan jenis target dariMsebelum jenis penggantian parameter tidak berisi parameter jenis tetapi jenisNtarget tidak, maka memiliki lebih sedikit parameter jenis daripada jenisNtarget , hilangkanNdari set. Contohnya:Imports System.Runtime.CompilerServices Module Module1 Sub Main() Dim x As Integer = 1 x.f(1) ' Calls first "f" extension method Dim y As New Dictionary(Of Integer, Integer) y.g(1) ' Ambiguity error End Sub <Extension()> Sub f(x As Integer, z As Integer) End Sub <Extension()> Sub f(Of T)(x As T, z As T) End Sub <Extension()> Sub g(Of T)(y As Dictionary(Of T, Integer), z As T) End Sub <Extension()> Sub g(Of T)(y As Dictionary(Of T, T), z As T) End Sub End ModuleSebelum argumen jenis telah diganti, jika
Mkurang umum ( Generikitas Bagian) daripadaN, hilangkanNdari set.Jika
Mbukan metode ekstensi danNadalah, hilangkanNdari set.Jika
MdanNmerupakan metode ekstensi danMditemukan sebelumnyaN( Kumpulan Metode Ekstensi Bagian), hilangkanNdari set. Contohnya:Imports System.Runtime.CompilerServices Class C1 End Class Namespace N1 Module N1C1Extensions <Extension> _ Sub M1(c As C1, x As Integer) End Sub End Module End Namespace Namespace N1.N2 Module N2C1Extensions <Extension> _ Sub M1(c As C1, y As Integer) End Sub End Module End Namespace Namespace N1.N2.N3 Module Test Sub Main() Dim x As New C1() ' Calls N2C1Extensions.M1 x.M1(10) End Sub End Module End NamespaceJika metode ekstensi ditemukan dalam langkah yang sama, maka metode ekstensi tersebut ambigu. Panggilan mungkin selalu terdisambiguasi menggunakan nama modul standar yang berisi metode ekstensi dan memanggil metode ekstensi seolah-olah itu adalah anggota biasa. Contohnya:
Imports System.Runtime.CompilerServices Class C1 End Class Module C1ExtA <Extension> _ Sub M(c As C1) End Sub End Module Module C1ExtB <Extension> _ Sub M(c As C1) End Sub End Module Module Main Sub Test() Dim c As New C1() C1.M() ' Ambiguous between C1ExtA.M and BExtB.M C1ExtA.M(c) ' Calls C1ExtA.M C1ExtB.M(c) ' Calls C1ExtB.M End Sub End ModuleJika
MdanNkedua inferensi jenis yang diperlukan untuk menghasilkan argumen jenis, danMtidak memerlukan penentuan jenis dominan untuk salah satu argumen jenisnya (yaitu setiap argumen jenis yang disimpulkan ke satu jenis), tetapiNtidak, hilangkanNdari set.Nota. Aturan ini memastikan bahwa resolusi kelebihan beban yang berhasil dalam versi sebelumnya (di mana menyimpulkan beberapa jenis untuk argumen jenis akan menyebabkan kesalahan), terus menghasilkan hasil yang sama.
Jika resolusi kelebihan beban sedang dilakukan untuk menyelesaikan target ekspresi pembuatan delegasi dari
AddressOfekspresi, dan delegasi danMmerupakan fungsi sementaraNmerupakan subroutine, hilangkanNdari set. Demikian juga, jika delegasi danMmerupakan subroutine, sementaraNitu adalah fungsi, hilangkanNdari set.Jika
Mtidak menggunakan default parameter opsional sebagai pengganti argumen eksplisit, tetapiNmelakukannya, maka hilangkanNdari set.Sebelum argumen jenis diganti, jika
Mmemiliki kedalaman generikitas yang lebih besar ( Generikitas Bagian) daripadaN, maka hilangkanNdari set.
Jika tidak, panggilan bersifat ambigu dan terjadi kesalahan waktu kompilasi.
Kekhususan anggota/jenis yang diberi daftar argumen
Anggota M dianggap sama spesifiknya dengan N, diberikan daftar Aargumen , jika tanda tangan mereka sama atau jika setiap jenis M parameter sama dengan jenis parameter yang sesuai di N.
Nota. Dua anggota dapat berakhir dalam grup metode dengan tanda tangan yang sama karena metode ekstensi. Dua anggota juga dapat sama-sama spesifik tetapi tidak memiliki tanda tangan yang sama karena parameter jenis atau ekspansi paramarray.
Anggota M dianggap lebih spesifik daripada N jika tanda tangan mereka berbeda dan setidaknya satu jenis parameter di M lebih spesifik daripada jenis parameter di N, dan tidak ada jenis parameter yang N lebih spesifik daripada jenis parameter di M. Mengingat sepasang parameter Mj dan Nj yang cocok dengan argumen Aj, jenis Mj dianggap lebih spesifik daripada jenis Nj jika salah satu kondisi berikut ini benar:
Ada konversi yang melebar dari jenis ke jenis
MjNj. (Catatan. Karena jenis parameter sedang dibandingkan tanpa memperhatikan argumen aktual dalam kasus ini, konversi yang melebar dari ekspresi konstanta ke jenis numerik yang cocok dengan nilai tidak dipertimbangkan dalam kasus ini.)Ajadalah literal0,Mjadalah jenis numerik danNjmerupakan jenis enumerasi. (Catatan. Aturan ini diperlukan karena harfiah0melebar ke jenis enumerasi apa pun. Karena jenis enumerasi melebar ke jenis yang mendasar, ini berarti bahwa resolusi kelebihan beban pada0akan, secara default, lebih memilih jenis enumerasi daripada jenis numerik. Kami menerima banyak umpan balik bahwa perilaku ini berlawanan.)MjdanNjkeduanya adalah jenis numerik, danMjdatang lebih awal dariNjdalam daftarByte,SByteShort,UShort,Integer,UIntegerLong,ULong,Decimal,Single, .Double(Catatan. Aturan tentang jenis numerik berguna karena jenis numerik yang ditandatangani dan tidak ditandatangani dari ukuran tertentu hanya memiliki konversi yang mempersempit di antaranya. Aturan di atas memutus dasi antara dua jenis yang mendukung jenis numerik yang lebih "alami". Ini sangat penting ketika melakukan resolusi kelebihan beban pada jenis yang melebar ke jenis numerik yang ditandatangani dan tidak ditandatangani dengan ukuran tertentu, misalnya, literal numerik yang cocok dengan keduanya.)MjdanNjmendelegasikan jenis fungsi dan jenisMjpengembalian lebih spesifik daripada jenisNjpengembalian IfAjdiklasifikasikan sebagai metode lambda, danMjatauNjadalahSystem.Linq.Expressions.Expression(Of T), maka argumen jenis jenis (dengan asumsi itu adalah jenis delegasi) digantikan untuk jenis yang dibandingkan.Mjidentik dengan jenisAj, danNjtidak. (Catatan. Menarik untuk dicatat bahwa aturan sebelumnya sedikit berbeda dari C#, dalam C# tersebut mengharuskan jenis fungsi delegasi memiliki daftar parameter yang identik sebelum membandingkan jenis pengembalian, sementara Visual Basic tidak.)
Generikitas
Anggota M bertekad kurang umum daripada anggota N sebagai berikut:
- Jika, untuk setiap pasangan parameter
Mjyang cocok danNj,Mjkurang atau sama generiknya dibandingkanNjdengan parameter jenis pada metode , dan setidaknya satuMjkurang umum sehubungan dengan parameter jenis pada metode . - Jika tidak, jika untuk setiap pasangan parameter
Mjyang cocok danNj,Mjkurang atau sama generiknya dibandingkanNjdengan parameter jenis pada jenis, dan setidaknya satuMjkurang umum sehubungan dengan parameter jenis pada jenis, makaMkurang generik daripadaN.
Parameter M dianggap sama generiknya dengan parameter N jika jenisnya Mt dan Nt keduanya merujuk ke parameter jenis atau keduanya tidak merujuk ke parameter jenis.
M dianggap kurang umum daripada N jika Mt tidak merujuk ke parameter jenis dan Nt tidak.
Contohnya:
Class C1(Of T)
Sub S1(Of U)(x As U, y As T)
End Sub
Sub S1(Of U)(x As U, y As U)
End Sub
Sub S2(x As Integer, y As T)
End Sub
Sub S2(x As T, y As T)
End Sub
End Class
Module Test
Sub Main()
Dim x As C1(Of Integer) = New C1(Of Integer)
x.S1(10, 10) ' Calls S1(U, T)
x.S2(10, 10) ' Calls S2(Integer, T)
End Sub
End Module
Parameter jenis metode ekstensi yang diperbaiki selama kari dianggap sebagai parameter jenis pada jenis, bukan parameter jenis pada metode . Contohnya:
Imports System.Runtime.CompilerServices
Module Ext1
<Extension> _
Sub M1(Of T, U)(x As T, y As U, z As U)
End Sub
End Module
Module Ext2
<Extension> _
Sub M1(Of T, U)(x As T, y As U, z As T)
End Sub
End Module
Module Test
Sub Main()
Dim i As Integer = 10
i.M1(10, 10)
End Sub
End Module
Kedalaman generikitas
Anggota M bertekad untuk memiliki kedalaman generik yang lebih besar daripada anggota N jika, untuk setiap pasangan parameter Mj yang cocok dan Nj, Mj memiliki kedalaman generikitas yang lebih Njbesar atau sama dengan , dan setidaknya satu Mj memiliki kedalaman generikitas yang lebih besar. Kedalaman generikitas didefinisikan sebagai berikut:
Apa pun selain parameter jenis memiliki kedalaman generik yang lebih besar daripada parameter jenis;
Secara rekursif, jenis yang dibangun memiliki kedalaman generik yang lebih besar daripada jenis konstruksi lain (dengan jumlah argumen jenis yang sama) jika setidaknya satu argumen jenis memiliki kedalaman generikitas yang lebih besar dan tidak ada argumen jenis yang memiliki lebih sedikit kedalaman daripada argumen jenis yang sesuai di yang lain.
Jenis array memiliki kedalaman generikitas yang lebih besar daripada jenis array lain (dengan jumlah dimensi yang sama) jika jenis elemen pertama memiliki kedalaman generikitas yang lebih besar daripada jenis elemen kedua.
Contohnya:
Module Test
Sub f(Of T)(x As Task(Of T))
End Sub
Sub f(Of T)(x As T)
End Sub
Sub Main()
Dim x As Task(Of Integer) = Nothing
f(x) ' Calls the first overload
End Sub
End Module
Penerapan ke Daftar Argumen
Metode berlaku untuk sekumpulan argumen jenis, argumen posisi, dan argumen bernama jika metode dapat dipanggil menggunakan daftar argumen. Daftar argumen dicocokkan dengan daftar parameter sebagai berikut:
- Pertama, cocokkan setiap argumen posisi untuk daftar parameter metode. Jika ada lebih banyak argumen posisi daripada parameter dan parameter terakhir bukan paramarray, metode ini tidak berlaku. Jika tidak, parameter paramarray diperluas dengan parameter jenis elemen paramarray agar sesuai dengan jumlah argumen posisi. Jika argumen posisi dihilangkan yang akan masuk ke paramarray, metode tidak berlaku.
- Selanjutnya, cocokkan setiap argumen bernama dengan parameter dengan nama yang diberikan. Jika salah satu argumen bernama gagal dicocokkan, cocok dengan parameter paramarray, atau cocok dengan argumen yang sudah cocok dengan argumen posisi atau bernama lain, metode tidak berlaku.
- Selanjutnya, jika argumen jenis telah ditentukan, argumen tersebut dicocokkan dengan daftar parameter jenis . Jika kedua daftar tidak memiliki jumlah elemen yang sama, metode tidak berlaku, kecuali daftar argumen jenis kosong. Jika daftar argumen jenis kosong, inferensi jenis digunakan untuk mencoba dan menyimpulkan daftar argumen jenis. Jika inferensi jenis gagal, metode ini tidak berlaku. Jika tidak, argumen jenis diisi di tempat parameter jenis dalam tanda tangan. Jika parameter yang belum dicocokkan tidak opsional, metode ini tidak berlaku.
- Jika ekspresi argumen tidak secara implisit dapat dikonversi ke jenis parameter yang cocok, maka metode tidak berlaku.
- Jika parameter adalah ByRef, dan tidak ada konversi implisit dari jenis parameter ke jenis argumen, maka metode tidak berlaku.
- Jika argumen jenis melanggar batasan metode (termasuk argumen jenis yang disimpulkan dari Langkah 3), metode tidak berlaku. Contohnya:
Module Module1
Sub Main()
f(Of Integer)(New Exception)
' picks the first overload (narrowing),
' since the second overload (widening) violates constraints
End Sub
Sub f(Of T)(x As IComparable)
End Sub
Sub f(Of T As Class)(x As Object)
End Sub
End Module
Jika ekspresi argumen tunggal cocok dengan parameter paramarray dan jenis ekspresi argumen dapat dikonversi ke jenis parameter paramarray dan jenis elemen paramarray, metode ini berlaku dalam bentuk yang diperluas dan tidak diperluas, dengan dua pengecualian. Jika konversi dari jenis ekspresi argumen ke jenis paramarray dipersempit, maka metode hanya berlaku dalam bentuk yang diperluas. Jika ekspresi argumen adalah harfiah Nothing, maka metode hanya berlaku dalam bentuknya yang tidak terlampaui. Contohnya:
Module Test
Sub F(ParamArray a As Object())
Dim o As Object
For Each o In a
Console.Write(o.GetType().FullName)
Console.Write(" ")
Next o
Console.WriteLine()
End Sub
Sub Main()
Dim a As Object() = { 1, "Hello", 123.456 }
Dim o As Object = a
F(a)
F(CType(a, Object))
F(o)
F(CType(o, Object()))
End Sub
End Module
Contoh di atas menghasilkan output berikut:
System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double
Dalam pemanggilan Fpertama dan terakhir , bentuk F normal berlaku karena konversi yang melebar ada dari jenis argumen ke jenis parameter (keduanya berjenis Object()), dan argumen diteruskan sebagai parameter nilai reguler. Dalam pemanggilan kedua dan ketiga, bentuk F normal tidak berlaku karena tidak ada konversi yang melebar dari jenis argumen ke jenis parameter (konversi dari Object ke Object() penyempitan). Namun, bentuk F yang diperluas berlaku, dan satu elemen Object() dibuat oleh pemanggilan. Elemen tunggal array diinisialisasi dengan nilai argumen yang diberikan (yang merupakan referensi ke Object()).
Meneruskan Argumen, dan Memilih Argumen untuk Parameter Opsional
Jika parameter adalah parameter nilai, ekspresi argumen yang cocok harus diklasifikasikan sebagai nilai. Nilai dikonversi ke jenis parameter dan diteruskan sebagai parameter pada waktu proses. Jika parameter adalah parameter referensi dan ekspresi argumen yang cocok diklasifikasikan sebagai variabel yang jenisnya sama dengan parameter, maka referensi ke variabel diteruskan sebagai parameter pada waktu proses.
Jika tidak, jika ekspresi argumen yang cocok diklasifikasikan sebagai variabel, nilai, atau akses properti, maka variabel sementara dari jenis parameter dialokasikan. Sebelum pemanggilan metode pada run time, ekspresi argumen diklasifikasikan ulang sebagai nilai, dikonversi ke jenis parameter, dan ditetapkan ke variabel sementara. Kemudian referensi ke variabel sementara diteruskan sebagai parameter . Setelah pemanggilan metode dievaluasi, jika ekspresi argumen diklasifikasikan sebagai variabel atau akses properti, variabel sementara ditetapkan ke ekspresi variabel atau ekspresi akses properti. Jika ekspresi akses properti tidak Set memiliki aksesor, maka penugasan tidak dilakukan.
Untuk parameter opsional di mana argumen belum disediakan, pengkompilasi memilih argumen seperti yang dijelaskan di bawah ini. Dalam semua kasus, ia menguji terhadap jenis parameter setelah substitusi jenis generik.
Jika parameter opsional memiliki atribut
System.Runtime.CompilerServices.CallerLineNumber, dan pemanggilan berasal dari lokasi dalam kode sumber, dan literal numerik yang mewakili nomor baris lokasi tersebut memiliki konversi intrinsik ke jenis parameter, maka literal numerik digunakan. Jika pemanggilan mencakup beberapa baris, maka pilihan baris mana yang akan digunakan bergantung pada implementasi.Jika parameter opsional memiliki atribut
System.Runtime.CompilerServices.CallerFilePath, dan pemanggilan berasal dari lokasi dalam kode sumber, dan string literal yang mewakili jalur file lokasi tersebut memiliki konversi intrinsik ke jenis parameter, maka literal string digunakan. Format jalur file bergantung pada implementasi.Jika parameter opsional memiliki atribut
System.Runtime.CompilerServices.CallerMemberName, dan pemanggilan berada dalam isi anggota jenis atau dalam atribut yang diterapkan ke bagian mana pun dari anggota jenis tersebut, dan string harfiah yang mewakili nama anggota tersebut memiliki konversi intrinsik ke jenis parameter, maka literal string digunakan. Untuk pemanggilan yang merupakan bagian dari pengaktor properti atau penanganan aktivitas kustom, maka nama anggota yang digunakan adalah properti atau peristiwa itu sendiri. Untuk pemanggilan yang merupakan bagian dari operator atau konstruktor, maka nama khusus implementasi digunakan.
Jika tidak ada yang berlaku di atas, maka nilai default parameter opsional digunakan (atau Nothing jika tidak ada nilai default yang disediakan). Dan jika lebih dari satu dari yang di atas berlaku, maka pilihan yang akan digunakan tergantung pada implementasi.
Atribut CallerLineNumber dan CallerFilePath berguna untuk pengelogan.
CallerMemberName berguna untuk menerapkan INotifyPropertyChanged. Berikut adalah contohnya.
Sub Log(msg As String,
<CallerFilePath> Optional file As String = Nothing,
<CallerLineNumber> Optional line As Integer? = Nothing)
Console.WriteLine("{0}:{1} - {2}", file, line, msg)
End Sub
WriteOnly Property p As Integer
Set(value As Integer)
Notify(_p, value)
End Set
End Property
Private _p As Integer
Sub Notify(Of T As IEquatable(Of T))(ByRef v1 As T, v2 As T,
<CallerMemberName> Optional prop As String = Nothing)
If v1 IsNot Nothing AndAlso v1.Equals(v2) Then Return
If v1 Is Nothing AndAlso v2 Is Nothing Then Return
v1 = v2
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
End Sub
Selain parameter opsional di atas, Microsoft Visual Basic juga mengenali beberapa parameter opsional tambahan jika diimpor dari metadata (yaitu dari referensi DLL):
Setelah mengimpor dari metadata, Visual Basic juga memperlakukan parameter
<Optional>sebagai indikasi bahwa parameter bersifat opsional: dengan cara ini dimungkinkan untuk mengimpor deklarasi yang memiliki parameter opsional tetapi tidak ada nilai default, meskipun ini tidak dapat diekspresikan menggunakanOptionalkata kunci.Jika parameter opsional memiliki atribut
Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute, dan harfiah numerik 1 atau 0 memiliki konversi ke jenis parameter, maka pengkompilasi menggunakan sebagai argumen baik literal 1 jikaOption Compare Textberlaku, atau literal 0 jikaOptional Compare Binaryberlaku.Jika parameter opsional memiliki atribut
System.Runtime.CompilerServices.IDispatchConstantAttribute, dan memiliki jenisObject, dan tidak menentukan nilai default, maka pengkompilasi menggunakan argumenNew System.Runtime.InteropServices.DispatchWrapper(Nothing).Jika parameter opsional memiliki atribut
System.Runtime.CompilerServices.IUnknownConstantAttribute, dan memiliki jenisObject, dan tidak menentukan nilai default, maka pengkompilasi menggunakan argumenNew System.Runtime.InteropServices.UnknownWrapper(Nothing).Jika parameter opsional memiliki jenis
Object, dan tidak menentukan nilai default, maka pengkompilasi menggunakan argumenSystem.Reflection.Missing.Value.
Metode Bersyarah
Jika metode target yang dirujuk oleh ekspresi pemanggilan adalah subroutine yang bukan anggota antarmuka dan jika metode memiliki satu atau beberapa System.Diagnostics.ConditionalAttribute atribut, evaluasi ekspresi tergantung pada konstanta kompilasi bersyarkat yang ditentukan pada titik tersebut dalam file sumber. Setiap instans atribut menentukan string, yang menamai konstanta kompilasi bersyarkat. Setiap konstanta kompilasi bersyar dievaluasi seolah-olah itu adalah bagian dari pernyataan kompilasi bersyarkat. Jika konstanta mengevaluasi ke True, ekspresi dievaluasi secara normal pada waktu proses. Jika konstanta mengevaluasi ke False, ekspresi tidak dievaluasi sama sekali.
Saat mencari atribut , deklarasi yang paling turunan dari metode yang dapat diambil alih diperiksa.
Nota. Atribut tidak valid pada fungsi atau metode antarmuka dan diabaikan jika ditentukan pada salah satu jenis metode. Dengan demikian, metode bersyarat hanya akan muncul dalam pernyataan pemanggilan.
Ketik Inferensi Argumen
Ketika metode dengan parameter jenis dipanggil tanpa menentukan argumen jenis, ketik inferensi argumen digunakan untuk mencoba dan menyimpulkan argumen jenis untuk panggilan. Ini memungkinkan sintaks yang lebih alami untuk digunakan untuk memanggil metode dengan parameter jenis ketika argumen jenis dapat disimpulkan secara sepele. Misalnya, mengingat deklarasi metode berikut:
Module Util
Function Choose(Of T)(b As Boolean, first As T, second As T) As T
If b Then
Return first
Else
Return second
End If
End Function
End Class
dimungkinkan Choose untuk memanggil metode tanpa secara eksplisit menentukan argumen jenis:
' calls Choose(Of Integer)
Dim i As Integer = Util.Choose(True, 5, 213)
' calls Choose(Of String)
Dim s As String = Util.Choose(False, "a", "b")
Melalui inferensi argumen jenis, argumen Integer jenis dan String ditentukan dari argumen ke metode .
Inferensi argumen jenis terjadi sebelum reklasifikasi ekspresi dilakukan pada metode lambda atau penunjuk metode dalam daftar argumen, karena reklassifikasi dari kedua jenis ekspresi tersebut mungkin memerlukan jenis parameter untuk diketahui. Mengingat sekumpulan argumen A1,...,An, sekumpulan parameter P1,...,Pn yang cocok dan sekumpulan parameter T1,...,Tnjenis metode , dependensi antara argumen dan parameter jenis metode pertama kali dikumpulkan sebagai berikut:
Jika
AnharfiahNothing, tidak ada dependensi yang dihasilkan.Jika
Anadalah metode lambda dan jenisnyaPnadalah jenis delegasi yang dibangun atauSystem.Linq.Expressions.Expression(Of T), di manaTadalah jenis delegasi yang dibangun,Jika jenis parameter metode lambda akan disimpulkan dari jenis parameter
Pnyang sesuai , dan jenis parameter tergantung pada parameterTnjenis metode , makaAnmemiliki dependensi padaTn.Jika jenis parameter metode lambda ditentukan dan jenis parameter
Pnyang sesuai tergantung pada parameterTnjenis metode , makaTnmemiliki dependensi padaAn.Jika jenis
Pnpengembalian tergantung pada parameterTnjenis metode , makaTnmemiliki dependensi padaAn.Jika
Anadalah penunjuk metode dan jenisnyaPnadalah jenis delegasi yang dibangun,Jika jenis
Pnpengembalian tergantung pada parameterTnjenis metode , makaTnmemiliki dependensi padaAn.Jika
Pnadalah jenis yang dibangun dan jenisPntergantung pada parameterTnjenis metode , makaTnmemiliki dependensi padaAn.Jika tidak, tidak ada dependensi yang dihasilkan.
Setelah mengumpulkan dependensi, argumen apa pun yang tidak memiliki dependensi akan dihilangkan. Jika ada parameter jenis metode yang tidak memiliki dependensi keluar (yaitu parameter jenis metode tidak bergantung pada argumen), maka inferensi jenis gagal. Jika tidak, argumen dan parameter jenis metode yang tersisa dikelompokkan ke dalam komponen yang sangat terhubung. Komponen yang sangat terhubung adalah sekumpulan argumen dan parameter jenis metode, di mana elemen apa pun dalam komponen dapat dijangkau melalui dependensi pada elemen lain.
Komponen yang terhubung kuat kemudian diurutkan secara topologis dan diproses dalam urutan topologis:
Jika komponen yang sangat diketik hanya berisi satu elemen,
Jika elemen telah ditandai selesai, lewati.
Jika elemen adalah argumen, tambahkan petunjuk jenis dari argumen ke parameter jenis metode yang bergantung padanya dan tandai elemen sebagai selesai. Jika argumen adalah metode lambda dengan parameter yang masih memerlukan jenis yang disimpulkan, maka simpulkan
Objectuntuk jenis parameter tersebut.Jika elemen adalah parameter jenis metode, maka menyimpulkan parameter jenis metode menjadi jenis dominan di antara petunjuk jenis argumen dan menandai elemen sebagai selesai. Jika petunjuk jenis memiliki batasan elemen array di dalamnya, maka hanya konversi yang valid di antara array dari jenis yang diberikan yang dipertimbangkan (yaitu konversi array kovarian dan intrinsik). Jika petunjuk jenis memiliki batasan argumen umum di dalamnya, maka hanya konversi identitas yang dipertimbangkan. Jika tidak ada jenis dominan yang dapat dipilih, inferensi gagal. Jika ada jenis argumen metode lambda tergantung pada parameter jenis metode ini, jenisnya disebarkan ke metode lambda.
Jika komponen yang sangat diketik berisi lebih dari satu elemen, maka komponen berisi siklus.
Untuk setiap parameter jenis metode yang merupakan elemen dalam komponen, jika parameter jenis metode bergantung pada argumen yang tidak ditandai selesai, konversikan dependensi tersebut menjadi pernyataan yang akan diperiksa di akhir proses inferensi.
Mulai ulang proses inferensi pada titik di mana komponen yang sangat diketik ditentukan.
Jika inferensi jenis berhasil untuk semua parameter jenis metode, maka dependensi apa pun yang diubah menjadi pernyataan akan diperiksa. Pernyataan berhasil jika jenis argumen secara implisit dapat dikonversi ke jenis parameter jenis metode yang disimpulkan. Jika pernyataan gagal, maka ketik inferensi argumen gagal.
Mengingat jenis Ta argumen untuk argumen A dan jenis Tp parameter untuk parameter P, petunjuk jenis dihasilkan sebagai berikut:
Jika
Tptidak melibatkan parameter jenis metode apa pun, maka tidak ada petunjuk yang dihasilkan.Jika
TpdanTamerupakan jenis array dari peringkat yang sama, gantiTadanTpdengan jenisTaelemen danTpdan mulai ulang proses ini dengan pembatasan elemen array.Jika
Tpadalah parameter jenis metode, makaTaditambahkan sebagai petunjuk jenis dengan batasan saat ini, jika ada.Jika
Aadalah metode lambda danTpmerupakan jenis delegasi yang dibangun atauSystem.Linq.Expressions.Expression(Of T), di manaTmerupakan jenis delegasi yang dibangun, untuk setiap jenis parameter metode lambda dan jenisTLTDparameter delegasi yang sesuai, gantiTadenganTLdanTpdenganTDdan mulai ulang proses tanpa batasan. Kemudian, gantiTadengan jenis pengembalian metode lambda dan:- jika
Aadalah metode lambda biasa, gantiTpdengan jenis pengembalian jenis delegasi; - jika
Aadalah metode lambda asinkron dan jenis pengembalian jenis delegasi memiliki formulirTask(Of T)untuk beberapaT, gantiTpdengan ituT; - jika
Aadalah metode lambda iterator dan jenis pengembalian dari jenis delegasi memiliki formulirIEnumerator(Of T)atauIEnumerable(Of T)untuk beberapaT, gantiTpdengan yangT. - Selanjutnya, mulai ulang proses tanpa batasan.
- jika
Jika
Aadalah penunjuk metode danTpmerupakan jenis delegasi yang dibangun, gunakan jenisTpparameter untuk menentukan metode mana yang ditunjuk paling berlaku untukTp. Jika ada metode yang paling berlaku, gantiTadengan jenis pengembalian metode danTpdengan jenis pengembalian jenis delegasi dan mulai ulang proses tanpa batasan.Jika tidak,
Tpharus merupakan jenis yang dibangun. MengingatTG, jenis generik dariTp,Jika
TaadalahTG, mewarisi dariTG, atau mengimplementasikan jenisTGtepat sekali, maka untuk setiap argumenTaxjenis yang cocok dari danTpxdariTaTp, gantiTadenganTaxdanTpdenganTpxdan mulai ulang proses dengan pembatasan argumen generik.Jika tidak, inferensi jenis gagal untuk metode generik.
Keberhasilan inferensi jenis tidak, dalam dan dari dirinya sendiri, menjamin bahwa metode tersebut berlaku.
Visual Basic language spec