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.
Ekspresi adalah urutan operator dan operand yang menentukan komputasi nilai, atau yang menunjuk variabel atau konstanta. Bab ini mendefinisikan sintaksis, urutan evaluasi operand dan operator, dan arti ekspresi.
Expression
: SimpleExpression
| TypeExpression
| MemberAccessExpression
| DictionaryAccessExpression
| InvocationExpression
| IndexExpression
| NewExpression
| CastExpression
| OperatorExpression
| ConditionalExpression
| LambdaExpression
| QueryExpression
| XMLLiteralExpression
| XMLMemberAccessExpression
;
Klasifikasi Ekspresi
Setiap ekspresi diklasifikasikan sebagai salah satu hal berikut:
Sebuah nilai. Setiap nilai memiliki jenis terkait.
Sebuah variabel. Setiap variabel memiliki jenis terkait, yaitu jenis variabel yang dideklarasikan.
Sebuah namespace. Ekspresi dengan klasifikasi ini hanya dapat muncul sebagai sisi kiri akses anggota. Dalam konteks lain, ekspresi yang diklasifikasikan sebagai namespace menyebabkan kesalahan waktu kompilasi.
Sebuah jenis. Ekspresi dengan klasifikasi ini hanya dapat muncul sebagai sisi kiri akses anggota. Dalam konteks lain, ekspresi yang diklasifikasikan sebagai jenis menyebabkan kesalahan waktu kompilasi.
Grup metode, yang merupakan sekumpulan metode yang kelebihan beban pada nama yang sama. Grup metode mungkin memiliki ekspresi target terkait dan daftar argumen jenis terkait.
Penunjuk metode, yang mewakili lokasi metode. Penunjuk metode mungkin memiliki ekspresi target terkait dan daftar argumen jenis terkait.
Metode lambda, yang merupakan metode anonim.
Grup properti, yang merupakan sekumpulan properti yang kelebihan beban pada nama yang sama. Grup properti mungkin memiliki ekspresi target terkait.
Akses properti. Setiap akses properti memiliki tipe yang terkait, yaitu tipe dari properti tersebut. Akses properti mungkin memiliki ekspresi target terkait.
Akses yang terlambat terikat, yang mewakili metode atau akses properti yang ditangguhkan hingga run-time. Akses yang terlambat terikat mungkin memiliki ekspresi target terkait dan daftar argumen jenis terkait. Jenis akses yang terlambat terikat selalu
Object.Akses acara. Setiap akses peristiwa memiliki jenis terkait, yaitu jenis peristiwa tersebut. Akses peristiwa mungkin memiliki ekspresi target terkait. Akses peristiwa mungkin muncul sebagai argumen pertama dari
RaiseEventpernyataan , ,AddHandlerdanRemoveHandler. Dalam konteks lain, ekspresi yang diklasifikasikan sebagai akses ke peristiwa akan menyebabkan kesalahan saat kompilasi.Array literal, yang mewakili nilai awal array yang jenisnya belum ditentukan.
Kosong. Ini terjadi ketika ekspresi adalah pemanggilan subroutine, atau ekspresi operator tunggu tanpa hasil. Ekspresi yang diklasifikasikan sebagai batal hanya valid dalam konteks pernyataan pemanggilan atau pernyataan tunggu.
Nilai default. Hanya literal
Nothingyang menghasilkan klasifikasi ini.
Hasil akhir ekspresi biasanya berupa nilai atau variabel, dengan kategori ekspresi lain yang berfungsi sebagai nilai perantara yang hanya diizinkan dalam konteks tertentu.
Perhatikan bahwa ekspresi yang jenisnya adalah parameter jenis dapat digunakan dalam pernyataan dan ekspresi yang mengharuskan jenis ekspresi memiliki karakteristik tertentu (seperti menjadi jenis referensi, jenis nilai, berasal dari beberapa jenis, dll.) jika batasan yang diberlakukan pada parameter jenis memenuhi karakteristik tersebut.
Reklasifikasi Ekspresi
Biasanya, ketika ekspresi digunakan dalam konteks yang memerlukan klasifikasi yang berbeda dari ekspresi, kesalahan waktu kompilasi terjadi -- misalnya, mencoba menetapkan nilai ke harfiah. Namun, dalam banyak kasus dimungkinkan untuk mengubah klasifikasi ekspresi melalui proses reklasifikasi.
Jika reklasifikasi berhasil, maka reklasifikasi dinilai melebar atau mempersempit. Kecuali dinyatakan lain, semua reklasifikasi dalam daftar ini melebar.
Jenis ekspresi berikut dapat diklasifikasikan ulang:
Variabel dapat diklasifikasi ulang sebagai nilai. Nilai yang disimpan dalam variabel diambil.
Grup metode dapat diklasifikasi ulang sebagai nilai. Ekspresi grup metode ditafsirkan sebagai ekspresi pemanggilan dengan ekspresi target terkait dan daftar parameter jenis, dan tanda kurung kosong (yaitu,
fditafsirkan sebagaif()danf(Of Integer)ditafsirkan sebagaif(Of Integer)()). Reklasifikasi ini dapat mengakibatkan ekspresi diklasifikasikan ulang lebih lanjut sebagai batal.Penunjuk metode dapat diklasifikasi ulang sebagai nilai. Reklasifikasi ini hanya dapat terjadi dalam konteks konversi tempat jenis target diketahui. Ekspresi penunjuk metode ditafsirkan sebagai argumen untuk mendelegasikan ekspresi instansiasi dari jenis yang sesuai dengan daftar argumen jenis terkait. Contohnya:
Delegate Sub D(i As Integer) Module Test Sub F(i As Integer) End Sub Sub Main() Dim del As D ' The next two lines are equivalent. del = AddressOf F del = New D(AddressOf F) End Sub End ModuleMetode lambda dapat diklasifikasi ulang sebagai nilai. Jika reklasifikasi terjadi dalam konteks konversi di mana jenis target diketahui, maka salah satu dari dua reklasifikasi dapat terjadi:
Jika jenis target adalah jenis delegasi, metode lambda ditafsirkan sebagai argumen ke ekspresi delegasi-konstruksi dari jenis yang sesuai.
Jika jenis target adalah
System.Linq.Expressions.Expression(Of T), danTmerupakan jenis delegasi, maka metode lambda ditafsirkan seolah-olah digunakan dalam ekspresi delegasi-konstruksi untukTdan kemudian dikonversi ke pohon ekspresi.
Metode lambda asinkron atau iterator hanya dapat ditafsirkan sebagai argumen ke ekspresi delegasi-konstruksi, jika delegasi tidak memiliki parameter ByRef.
Jika konversi dari salah satu jenis parameter delegasi ke jenis parameter lambda yang sesuai adalah konversi yang mempersempit, maka reklasifikasi dinilai sebagai penyempitan; jika tidak, itu melebar.
Nota. Terjemahan yang tepat antara metode lambda dan pohon ekspresi mungkin tidak diperbaiki antara versi kompilator dan berada di luar cakupan spesifikasi ini. Untuk Microsoft Visual Basic 11.0, semua ekspresi lambda dapat dikonversi ke pohon ekspresi yang tunduk pada batasan berikut: (1) 1. Hanya ekspresi lambda baris tunggal tanpa parameter ByRef yang dapat dikonversi ke pohon ekspresi. Dari lambda baris
Subtunggal, hanya pernyataan pemanggilan yang dapat dikonversi ke pohon ekspresi. (2) Ekspresi jenis anonim tidak dapat dikonversi ke pohon ekspresi jika penginisialisasi bidang sebelumnya digunakan untuk menginisialisasi penginisialisasi bidang berikutnya, misalnyaNew With {.a=1, .b=.a}. (3) Ekspresi penginisialisasi objek tidak dapat dikonversi ke pohon ekspresi jika anggota objek saat ini yang sedang diinisialisasi digunakan di salah satu penginisialisasi bidang, misalnyaNew C1 With {.a=1, .b=.Method1()}. (4) Ekspresi pembuatan array multi-dimensi hanya dapat dikonversi ke pohon ekspresi jika mereka mendeklarasikan jenis elemennya secara eksplisit. (5) Ekspresi pengikatan terlambat tidak dapat dikonversi ke pohon ekspresi. (6) Ketika variabel atau bidang diteruskan ByRef ke ekspresi pemanggilan tetapi tidak memiliki jenis yang sama persis dengan parameter ByRef, atau ketika properti diteruskan ByRef, semantik VB normal adalah bahwa salinan argumen diteruskan ByRef dan nilai akhirnya kemudian disalin kembali ke variabel atau bidang atau properti. Di pohon ekspresi, penyalinan kembali tidak terjadi. (7) Semua pembatasan ini juga berlaku untuk ekspresi lambda berlapis.Jika jenis target tidak diketahui, maka metode lambda ditafsirkan sebagai argumen untuk mendelegasikan ekspresi instansiasi dari jenis delegasi anonim dengan tanda tangan yang sama dari metode lambda. Jika semantik ketat digunakan dan jenis parameter apa pun dihilangkan, kesalahan waktu kompilasi terjadi; jika tidak,
Objectdiganti dengan jenis parameter yang hilang. Contohnya:Module Test Sub Main() ' Type of x will be equivalent to Func(Of Object, Object, Object) Dim x = Function(a, b) a + b ' Type of y will be equivalent to Action(Of Object, Object) Dim y = Sub(a, b) Console.WriteLine(a + b) End Sub End ModuleGrup properti dapat diklasifikasi ulang sebagai akses properti. Ekspresi grup properti ditafsirkan sebagai ekspresi indeks dengan tanda kurung kosong (yaitu,
fditafsirkan sebagaif()).Akses properti dapat diklasifikasi ulang sebagai nilai. Ekspresi akses properti ditafsirkan sebagai ekspresi pemanggilan aksesor
Getproperti. Jika properti tidak memiliki getter, maka terjadi kesalahan waktu kompilasi.Akses yang terlambat terikat dapat diklasifikasikan kembali sebagai metode terikat terlambat atau akses properti yang terlambat terikat. Dalam situasi di mana akses yang terlambat terikat dapat diklasifikasikan kembali baik sebagai akses metode maupun sebagai akses properti, reklasifikasi ke akses properti lebih disukai.
Akses yang terlambat terikat dapat diklasifikasi ulang sebagai nilai.
Array harfiah dapat diklasifikasikan ulang sebagai nilai. Jenis nilai ditentukan sebagai berikut:
Jika reklasifikasi terjadi dalam konteks konversi di mana jenis target diketahui dan jenis target adalah jenis array, maka array literal diklasifikasikan ulang sebagai nilai jenis T(). Jika jenis target adalah
System.Collections.Generic.IList(Of T), ,IReadOnlyList(Of T)ICollection(Of T),IReadOnlyCollection(Of T), atauIEnumerable(Of T), dan array literal memiliki satu tingkat bersarang, maka array literal diklasifikasikan ulang sebagai nilai jenisT().Jika tidak, array literal diklasifikasikan ulang ke nilai yang jenisnya adalah array peringkat yang sama dengan tingkat penumpasan digunakan, dengan jenis elemen yang ditentukan oleh jenis elemen dominan dalam inisialisasi; jika tidak ada jenis dominan yang dapat ditentukan,
Objectdigunakan. Contohnya:' x Is GetType(Double(,,)) Dim x = { { { 1, 2.0 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } }.GetType() ' y Is GetType(Integer()) Dim y = { 1, 2, 3 }.GetType() ' z Is GetType(Object()) Dim z = { 1, "2" }.GetType() ' Error: Inconsistent nesting Dim a = { { 10 }, { 20, 30 } }.GetType()
Nota. Ada sedikit perubahan perilaku antara bahasa versi 9.0 dan versi 10.0. Sebelum 10.0, inisialisasi elemen array tidak memengaruhi inferensi jenis variabel lokal dan sekarang mereka melakukannya. Jadi
Dim a() = { 1, 2, 3 }akan disimpulkanObject()sebagai jenisadalam versi 9.0 bahasa danInteger()dalam versi 10.0.Reklasifikasi kemudian menginterpretasikan ulang array secara harfiah sebagai ekspresi pembuatan array. Jadi contohnya:
Dim x As Double = { 1, 2, 3, 4 } Dim y = { "a", "b" }setara dengan:
Dim x As Double = New Double() { 1, 2, 3, 4 } Dim y = New String() { "a", "b" }Reklasifikasi dinilai menyempit jika ada konversi dari ekspresi elemen ke jenis elemen array yang menyempit; jika tidak, itu dinilai sebagai pellebaran.
Nilai
Nothingdefault dapat diklasifikasikan ulang sebagai nilai. Dalam konteks di mana jenis target diketahui, hasilnya adalah nilai default dari jenis target. Dalam konteks di mana jenis target tidak diketahui, hasilnya adalah nilai null dari jenisObject.
Ekspresi namespace, ekspresi jenis, ekspresi akses peristiwa, atau ekspresi kekosongan tidak dapat diklasifikasikan ulang. Beberapa reklasifikasi dapat dilakukan secara bersamaan. Contohnya:
Module Test
Sub F(i As Integer)
End Sub
ReadOnly Property P() As Integer
Get
End Get
End Sub
Sub Main()
F(P)
End Property
End Module
Dalam hal ini, ekspresi P grup properti pertama kali diklasifikasikan ulang dari grup properti ke akses properti lalu diklasifikasi ulang dari akses properti ke nilai. Jumlah reklasifikasi terkecil dilakukan untuk mencapai klasifikasi yang valid dalam konteks.
Ekspresi Konstanta
Ekspresi konstanta adalah ekspresi yang nilainya dapat dievaluasi sepenuhnya pada waktu kompilasi.
ConstantExpression
: Expression
;
Jenis ekspresi konstanta dapat berupa Byte, , SByte, UShort, UIntegerShort, Integer, ULong, Long, Char, Single, Double, Decimal, Date, Boolean, String, , Object, , atau jenis enumerasi apa pun. Konstruksi berikut diizinkan dalam ekspresi konstanta:
Literal (termasuk
Nothing).Referensi ke anggota jenis konstanta atau lokal konstanta.
Referensi ke anggota jenis enumerasi.
Subekspresi yang dikurung.
Ekspresi koersi, asalkan jenis target adalah salah satu jenis yang tercantum di atas. Paksaan ke dan dari
Stringadalah pengecualian untuk aturan ini dan hanya diizinkan pada nilai null karenaStringkonversi selalu dilakukan dalam budaya lingkungan eksekusi saat ini pada waktu proses. Perhatikan bahwa ekspresi koersi konstan hanya dapat menggunakan konversi intrinsik.Operator
+,-danNotunary, asalkan operand dan hasilnya adalah jenis yang tercantum di atas.Operator
+biner , ,*-,^Mod,/,<<>>AndOr&Xor<OrElseAndAlso\><>=, ,<=dan=>disediakan setiap operand dan hasilnya adalah jenis yang tercantum di atas.Operator bersyukur Jika, asalkan setiap operand dan hasilnya adalah jenis yang tercantum di atas.
Fungsi run-time berikut:
Microsoft.VisualBasic.Strings.ChrW;Microsoft.VisualBasic.Strings.Chrjika nilai konstanta antara 0 dan 128;Microsoft.VisualBasic.Strings.AscWjika string konstanta tidak kosong;Microsoft.VisualBasic.Strings.Ascjika string konstanta tidak kosong.
Konstruksi berikut tidak diizinkan dalam ekspresi konstanta:
- Pengikatan implisit melalui
Withkonteks.
Ekspresi konstan jenis integral (ULong, Long, , UInteger, IntegerUShort, Short, SByte, atau Byte) dapat dikonversi secara implisit ke jenis integral yang lebih sempit, dan ekspresi konstan jenis Double dapat dikonversi secara implisit ke Single, asalkan nilai ekspresi konstanta berada dalam rentang jenis tujuan. Konversi yang mempersempit ini diizinkan terlepas dari apakah semantik permisif atau ketat digunakan.
Ekspresi Late-Bound
Ketika target ekspresi akses anggota atau ekspresi indeks berjenis Object, pemrosesan ekspresi dapat ditangguhkan hingga run time. Menunda pemrosesan dengan cara ini disebut pengikatan terlambat. Pengikatan terlambat memungkinkan Object variabel digunakan dengan cara tanpa jenis , di mana semua resolusi anggota didasarkan pada jenis run-time aktual dari nilai dalam variabel. Jika semantik ketat ditentukan oleh lingkungan kompilasi atau oleh Option Strict, pengikatan terlambat menyebabkan kesalahan waktu kompilasi. Anggota non-publik diabaikan saat melakukan pengikatan terlambat, termasuk untuk tujuan resolusi kelebihan beban. Perhatikan bahwa, tidak seperti kasus awal yang terikat, memanggil atau mengakses Shared anggota terlambat terikat akan menyebabkan target pemanggilan dievaluasi pada waktu proses. Jika ekspresi adalah ekspresi pemanggilan untuk anggota yang ditentukan pada System.Object, pengikatan terlambat tidak akan terjadi.
Secara umum, akses yang terlambat terikat diselesaikan pada run time dengan mencari pengidentifikasi pada jenis run-time ekspresi yang sebenarnya. Jika pencarian anggota yang terlambat terikat gagal pada waktu proses, System.MissingMemberException pengecualian akan dilemparkan. Karena pencarian anggota yang terlambat terikat dilakukan hanya dari jenis run-time ekspresi target terkait, jenis run-time objek tidak pernah menjadi antarmuka. Oleh karena itu, tidak mungkin untuk mengakses anggota antarmuka dalam ekspresi akses anggota yang terlambat terikat.
Argumen untuk akses anggota yang terlambat terikat dievaluasi dalam urutan muncul dalam ekspresi akses anggota: bukan urutan parameter yang dideklarasikan dalam anggota yang terikat akhir. Contoh berikut mengilustrasikan perbedaan ini:
Class C
Public Sub f(ByVal x As Integer, ByVal y As Integer)
End Sub
End Class
Module Module1
Sub Main()
Console.Write("Early-bound: ")
Dim c As C = New C
c.f(y:=t("y"), x:=t("x"))
Console.Write(vbCrLf & "Late-bound: ")
Dim o As Object = New C
o.f(y:=t("y"), x:=t("x"))
End Sub
Function t(ByVal s As String) As Integer
Console.Write(s)
Return 0
End Function
End Module
Kode ini menampilkan:
Early-bound: xy
Late-bound: yx
Karena resolusi kelebihan beban yang terlambat terikat dilakukan pada jenis run-time argumen, ada kemungkinan bahwa ekspresi mungkin menghasilkan hasil yang berbeda berdasarkan apakah itu dievaluasi pada waktu kompilasi atau run time. Contoh berikut mengilustrasikan perbedaan ini:
Class Base
End Class
Class Derived
Inherits Base
End Class
Module Test
Sub F(b As Base)
Console.WriteLine("F(Base)")
End Sub
Sub F(d As Derived)
Console.WriteLine("F(Derived)")
End Sub
Sub Main()
Dim b As Base = New Derived()
Dim o As Object = b
F(b)
F(o)
End Sub
End Module
Kode ini menampilkan:
F(Base)
F(Derived)
Ekspresi Sederhana
Ekspresi sederhana adalah literal, ekspresi tanda kurung, ekspresi instans, atau ekspresi nama sederhana.
SimpleExpression
: LiteralExpression
| ParenthesizedExpression
| InstanceExpression
| SimpleNameExpression
| AddressOfExpression
;
Ekspresi Harfiah
Ekspresi harfiah mengevaluasi ke nilai yang diwakili oleh literal. Ekspresi harfiah diklasifikasikan sebagai nilai, kecuali untuk literal Nothing, yang diklasifikasikan sebagai nilai default.
LiteralExpression
: Literal
;
Ekspresi Yang Dikurung
Ekspresi yang dikurung terdiri dari ekspresi yang diapit dalam tanda kurung. Ekspresi yang dikurung diklasifikasikan sebagai nilai, dan ekspresi yang diapit harus diklasifikasikan sebagai nilai. Ekspresi yang dikurung mengevaluasi ke nilai ekspresi dalam tanda kurung.
ParenthesizedExpression
: OpenParenthesis Expression CloseParenthesis
;
Ekspresi Instans
Ekspresi instans adalah kata kunci Me. Ini hanya dapat digunakan dalam isi metode, konstruktor, atau aksesor properti yang tidak dibagikan. Ini diklasifikasikan sebagai nilai. Kata kunci Me mewakili instans jenis yang berisi metode atau aksesor properti yang sedang dijalankan. Jika konstruktor secara eksplisit memanggil konstruktor lain ( Konstruktor Bagian), Me tidak dapat digunakan sampai setelah panggilan konstruktor tersebut, karena instans belum dibangun.
InstanceExpression
: 'Me'
;
Ekspresi Nama Sederhana
Ekspresi nama sederhana terdiri dari satu pengidentifikasi diikuti oleh daftar argumen jenis opsional.
SimpleNameExpression
: Identifier ( OpenParenthesis 'Of' TypeArgumentList CloseParenthesis )?
;
Nama diselesaikan dan diklasifikasikan dengan "aturan resolusi nama sederhana" berikut:
Dimulai dengan blok penutup segera dan berlanjut dengan setiap blok luar yang tertutup (jika ada), jika pengidentifikasi cocok dengan nama variabel lokal, variabel statis, lokal konstanta, parameter jenis metode, atau parameter, maka pengidentifikasi mengacu pada entitas yang cocok.
Jika pengidentifikasi cocok dengan variabel lokal, variabel statis, atau lokal konstanta dan daftar argumen jenis disediakan, kesalahan waktu kompilasi terjadi. Jika pengidentifikasi cocok dengan parameter jenis metode dan daftar argumen jenis disediakan, tidak ada kecocokan yang terjadi dan resolusi berlanjut. Jika pengidentifikasi cocok dengan variabel lokal, variabel lokal yang cocok adalah fungsi implisit atau
Getaksesor mengembalikan variabel lokal, dan ekspresi adalah bagian dari ekspresi pemanggilan, pernyataan pemanggilan, atauAddressOfekspresi, maka tidak ada kecocokan yang terjadi dan resolusi berlanjut.Ekspresi diklasifikasikan sebagai variabel jika merupakan variabel lokal, variabel statis, atau parameter. Ekspresi diklasifikasikan sebagai jenis jika merupakan parameter jenis metode. Ekspresi diklasifikasikan sebagai nilai jika merupakan lokal konstan.
Untuk setiap jenis berlapis yang berisi ekspresi, mulai dari yang paling dalam dan masuk ke terluar, jika pencarian pengidentifikasi dalam jenis menghasilkan kecocokan dengan anggota yang dapat diakses:
- Jika anggota jenis yang cocok adalah parameter jenis, maka hasilnya diklasifikasikan sebagai jenis dan merupakan parameter jenis yang cocok. Jika daftar argumen jenis disediakan, tidak ada kecocokan yang terjadi dan resolusi berlanjut.
- Jika tidak, jika jenisnya adalah jenis penutup segera dan pencarian mengidentifikasi anggota jenis non-bersama, maka hasilnya sama dengan akses anggota formulir
Me.E(Of A), di manaEadalah pengidentifikasi danAmerupakan daftar argumen jenis, jika ada. - Jika tidak, hasilnya sama persis dengan akses anggota formulir
T.E(Of A), di manaTadalah jenis yang berisi anggota yang cocok,Eadalah pengidentifikasi, danAmerupakan daftar argumen jenis, jika ada. Dalam hal ini, ini adalah kesalahan bagi pengidentifikasi untuk merujuk ke anggota yang tidak dibagikan.
Untuk setiap namespace berlapis, mulai dari yang paling dalam dan masuk ke namespace layanan terluar, lakukan hal berikut:
- Jika namespace berisi jenis yang dapat diakses dengan nama yang diberikan dan memiliki jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, pengidentifikasi merujuk ke jenis tersebut dan diklasifikasikan sebagai jenis.
- Jika tidak, jika tidak ada daftar argumen jenis yang disediakan dan namespace berisi anggota namespace dengan nama yang diberikan, maka pengidentifikasi merujuk ke namespace tersebut dan diklasifikasikan sebagai namespace layanan.
- Jika tidak, jika namespace berisi satu atau beberapa modul standar yang dapat diakses, dan pencarian nama anggota pengidentifikasi menghasilkan kecocokan yang dapat diakses dalam tepat satu modul standar, maka hasilnya sama persis dengan akses anggota formulir
M.E(Of A), di manaMadalah modul standar yang berisi anggota yang cocok,Eadalah pengidentifikasi, danAmerupakan daftar argumen jenis, jika ada. Jika pengidentifikasi cocok dengan anggota jenis yang dapat diakses dalam lebih dari satu modul standar, kesalahan waktu kompilasi terjadi.
Jika file sumber memiliki satu atau beberapa alias impor, dan pengidentifikasi cocok dengan nama salah satunya, maka pengidentifikasi mengacu pada namespace atau jenis tersebut. Jika daftar argumen jenis disediakan, kesalahan waktu kompilasi terjadi.
Jika file sumber yang berisi referensi nama memiliki satu atau beberapa impor:
- Jika pengidentifikasi cocok dalam satu impor nama jenis yang dapat diakses dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, atau anggota jenis, maka pengidentifikasi merujuk ke jenis atau anggota jenis tersebut. Jika pengidentifikasi cocok dalam lebih dari satu impor nama jenis yang dapat diakses dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, atau anggota jenis yang dapat diakses, kesalahan waktu kompilasi terjadi.
- Jika tidak, jika tidak ada daftar argumen jenis yang disediakan dan pengidentifikasi cocok dalam satu impor nama namespace dengan jenis yang dapat diakses, maka pengidentifikasi merujuk ke namespace tersebut. Jika tidak ada daftar argumen jenis yang disediakan dan pengidentifikasi cocok dalam lebih dari satu impor nama namespace dengan jenis yang dapat diakses, kesalahan waktu kompilasi terjadi.
- Jika tidak, jika impor berisi satu atau beberapa modul standar yang dapat diakses, dan pencarian nama anggota pengidentifikasi menghasilkan kecocokan yang dapat diakses dalam tepat satu modul standar, maka hasilnya sama persis dengan akses anggota formulir
M.E(Of A), di manaMadalah modul standar yang berisi anggota yang cocok,Eadalah pengidentifikasi, danAmerupakan daftar argumen jenis, jika ada. Jika pengidentifikasi cocok dengan anggota jenis yang dapat diakses dalam lebih dari satu modul standar, kesalahan waktu kompilasi terjadi.
Jika lingkungan kompilasi mendefinisikan satu atau beberapa alias impor, dan pengidentifikasi cocok dengan nama salah satunya, maka pengidentifikasi mengacu pada namespace atau jenis tersebut. Jika daftar argumen jenis disediakan, kesalahan waktu kompilasi terjadi.
Jika lingkungan kompilasi mendefinisikan satu atau beberapa impor:
- Jika pengidentifikasi cocok dalam satu impor nama jenis yang dapat diakses dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, atau anggota jenis, maka pengidentifikasi merujuk ke jenis atau anggota jenis tersebut. Jika pengidentifikasi cocok dalam lebih dari satu impor nama jenis yang dapat diakses dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, atau anggota jenis, kesalahan waktu kompilasi terjadi.
- Jika tidak, jika tidak ada daftar argumen jenis yang disediakan dan pengidentifikasi cocok dalam satu impor nama namespace dengan jenis yang dapat diakses, maka pengidentifikasi merujuk ke namespace tersebut. Jika tidak ada daftar argumen jenis yang disediakan dan pengidentifikasi cocok dalam lebih dari satu impor nama namespace dengan jenis yang dapat diakses, kesalahan waktu kompilasi terjadi.
- Jika tidak, jika impor berisi satu atau beberapa modul standar yang dapat diakses, dan pencarian nama anggota pengidentifikasi menghasilkan kecocokan yang dapat diakses dalam tepat satu modul standar, maka hasilnya sama persis dengan akses anggota formulir
M.E(Of A), di manaMadalah modul standar yang berisi anggota yang cocok,Eadalah pengidentifikasi, danAmerupakan daftar argumen jenis, jika ada. Jika pengidentifikasi cocok dengan anggota jenis yang dapat diakses dalam lebih dari satu modul standar, kesalahan waktu kompilasi terjadi.
Jika tidak, nama yang diberikan oleh pengidentifikasi tidak terdefinisi.
Ekspresi nama sederhana yang tidak ditentukan adalah kesalahan waktu kompilasi.
Biasanya, nama hanya dapat terjadi sekali di namespace tertentu. Namun, karena namespace dapat dideklarasikan di beberapa rakitan .NET, dimungkinkan untuk memiliki situasi di mana dua rakitan menentukan jenis dengan nama yang sepenuhnya memenuhi syarat yang sama. Dalam hal ini, jenis yang dideklarasikan dalam kumpulan file sumber saat ini lebih disukai daripada jenis yang dideklarasikan dalam rakitan .NET eksternal. Jika tidak, namanya ambigu dan tidak ada cara untuk membedakan nama.
Ekspresi AddressOf
Ekspresi AddressOf digunakan untuk menghasilkan penunjuk metode. Ekspresi terdiri dari AddressOf kata kunci dan ekspresi yang harus diklasifikasikan sebagai grup metode atau akses yang terlambat terikat. Grup metode tidak dapat merujuk ke konstruktor.
Hasilnya diklasifikasikan sebagai penunjuk metode, dengan ekspresi target terkait yang sama dan ketik daftar argumen (jika ada) sebagai grup metode.
AddressOfExpression
: 'AddressOf' Expression
;
Ekspresi Jenis
Ekspresi jenis adalah GetType ekspresi, TypeOf...Is ekspresi, Is ekspresi, atau GetXmlNamespace ekspresi.
TypeExpression
: GetTypeExpression
| TypeOfIsExpression
| IsExpression
| GetXmlNamespaceExpression
;
Ekspresi GetType
Ekspresi GetType terdiri dari kata kunci GetType dan nama jenis.
GetTypeExpression
: 'GetType' OpenParenthesis GetTypeTypeName CloseParenthesis
;
GetTypeTypeName
: TypeName
| QualifiedOpenTypeName
;
QualifiedOpenTypeName
: Identifier TypeArityList? (Period IdentifierOrKeyword TypeArityList?)*
| 'Global' Period IdentifierOrKeyword TypeArityList?
(Period IdentifierOrKeyword TypeArityList?)*
;
TypeArityList
: OpenParenthesis 'Of' CommaList? CloseParenthesis
;
CommaList
: Comma Comma*
;
Ekspresi GetType diklasifikasikan sebagai nilai, dan nilainya adalah kelas pantulan (System.Type) yang mewakili GetTypeTypeName-nya. Jika GetTypeTypeName adalah parameter jenis, ekspresi akan mengembalikan System.Type objek yang sesuai dengan argumen jenis yang disediakan untuk parameter jenis pada run-time.
GetTypeTypeName bersifat khusus dengan dua cara:
Ini diizinkan untuk menjadi
System.Void, satu-satunya tempat dalam bahasa di mana nama jenis ini dapat dirujuk.Ini mungkin jenis generik yang dibangun dengan argumen jenis yang dihilangkan. Ini memungkinkan
GetTypeekspresi untuk mengembalikanSystem.Typeobjek yang sesuai dengan jenis generik itu sendiri.
Contoh berikut menunjukkan GetType ekspresi:
Module Test
Sub Main()
Dim t As Type() = { GetType(Integer), GetType(System.Int32), _
GetType(String), GetType(Double()) }
Dim i As Integer
For i = 0 To t.Length - 1
Console.WriteLine(t(i).Name)
Next i
End Sub
End Module
Output yang dihasilkan adalah:
Int32
Int32
String
Double[]
TypeOf... Adalah Ekspresi
Ekspresi TypeOf...Is digunakan untuk memeriksa apakah jenis run-time nilai kompatibel dengan jenis tertentu. Operand pertama harus diklasifikasikan sebagai nilai, tidak dapat menjadi metode lambda yang diklasifikasikan ulang, dan harus dari jenis referensi atau jenis parameter jenis yang tidak dibatasi. Operand kedua harus berupa nama jenis. Hasil ekspresi diklasifikasikan sebagai nilai dan merupakan Boolean nilai. Ekspresi mengevaluasi ke True jika jenis run-time operand memiliki konversi parameter identitas, default, referensi, array, jenis nilai, atau jenis ke jenis. False Kesalahan waktu kompilasi terjadi jika tidak ada konversi antara jenis ekspresi dan jenis tertentu.
TypeOfIsExpression
: 'TypeOf' Expression 'Is' LineTerminator? TypeName
;
Adalah Ekspresi
Ekspresi Is atau IsNot digunakan untuk melakukan perbandingan kesetaraan referensi.
IsExpression
: Expression 'Is' LineTerminator? Expression
| Expression 'IsNot' LineTerminator? Expression
;
Setiap ekspresi harus diklasifikasikan sebagai nilai dan jenis setiap ekspresi harus merupakan jenis referensi, jenis parameter jenis yang tidak dibatasi, atau jenis nilai yang dapat diubah ke null. Namun, jika jenis satu ekspresi adalah jenis parameter jenis yang tidak dibatasi atau jenis nilai nullable, ekspresi lainnya harus harfiah Nothing.
Hasilnya diklasifikasikan sebagai nilai dan di ketik sebagai Boolean. Operasi Is mengevaluasi ke True jika kedua nilai merujuk ke instans yang sama atau kedua nilai adalah Nothing, atau False sebaliknya. Operasi IsNot mengevaluasi ke False jika kedua nilai merujuk ke instans yang sama atau kedua nilai adalah Nothing, atau True sebaliknya.
Ekspresi GetXmlNamespace
Ekspresi GetXmlNamespace terdiri dari kata kunci GetXmlNamespace dan nama namespace XML yang dideklarasikan oleh file sumber atau lingkungan kompilasi.
GetXmlNamespaceExpression
: 'GetXmlNamespace' OpenParenthesis XMLNamespaceName? CloseParenthesis
;
Ekspresi GetXmlNamespace diklasifikasikan sebagai nilai, dan nilainya adalah instans System.Xml.Linq.XNamespace yang mewakili XMLNamespaceName. Jika jenis tersebut tidak tersedia, maka kesalahan waktu kompilasi akan terjadi.
Contohnya:
Imports <xmlns:db="http://example.org/database">
Module Test
Sub Main()
Dim db = GetXmlNamespace(db)
' The following are equivalent
Dim customer1 = _
New System.Xml.Linq.XElement(db + "customer", "Bob")
Dim customer2 = <db:customer>Bob</>
End Sub
End Module
Segala sesuatu di antara tanda kurung dianggap sebagai bagian dari nama namespace, sehingga aturan XML di sekitar hal-hal seperti spasi kosong berlaku. Contohnya:
Imports <xmlns:db-ns="http://example.org/database">
Module Test
Sub Main()
' Error, XML name expected
Dim db1 = GetXmlNamespace( db-ns )
' Error, ')' expected
Dim db2 = GetXmlNamespace(db _
)
' OK.
Dim db3 = GetXmlNamespace(db-ns)
End Sub
End Module
Ekspresi namespace XML juga dapat dihilangkan, dalam hal ini ekspresi mengembalikan objek yang mewakili namespace XML default.
Ekspresi Akses Anggota
Ekspresi akses anggota digunakan untuk mengakses anggota entitas.
MemberAccessExpression
: MemberAccessBase? Period IdentifierOrKeyword
( OpenParenthesis 'Of' TypeArgumentList CloseParenthesis )?
;
MemberAccessBase
: Expression
| NonArrayTypeName
| 'Global'
| 'MyClass'
| 'MyBase'
;
Akses anggota formulir E.I(Of A), di mana E adalah ekspresi, nama jenis non-array, kata kunci Global, atau dihilangkan dan I merupakan pengidentifikasi dengan daftar Aargumen jenis opsional , dievaluasi dan diklasifikasikan sebagai berikut:
Jika
Edihilangkan, maka ekspresi dari pernyataan yang segera berisiWithdigantiEdan akses anggota dilakukan. Jika tidak ada pernyataan yang berisiWith, kesalahan waktu kompilasi terjadi.Jika
Ediklasifikasikan sebagai namespace layanan atauEadalah kata kunciGlobal, maka pencarian anggota dilakukan dalam konteks namespace yang ditentukan. JikaIadalah nama anggota namespace layanan yang dapat diakses dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, maka hasilnya adalah anggota tersebut. Hasilnya diklasifikasikan sebagai namespace layanan atau jenis tergantung pada anggota. Jika tidak, terjadi kesalahan waktu kompilasi.Jika
Eadalah jenis atau ekspresi yang diklasifikasikan sebagai jenis, maka pencarian anggota dilakukan dalam konteks jenis yang ditentukan. JikaIadalah nama anggota yang dapat diakses dariE, makaE.Idievaluasi dan diklasifikasikan sebagai berikut:- Jika
Iadalah kata kunciNewdanEbukan enumerasi, maka kesalahan waktu kompilasi terjadi. - Jika
Imengidentifikasi jenis dengan jumlah parameter jenis yang sama seperti yang disediakan dalam daftar argumen jenis, jika ada, maka hasilnya adalah jenis tersebut. - Jika
Imengidentifikasi satu atau beberapa metode, maka hasilnya adalah grup metode dengan daftar argumen jenis terkait dan tidak ada ekspresi target terkait. - Jika
Imengidentifikasi satu atau beberapa properti dan tidak ada daftar argumen jenis yang disediakan, maka hasilnya adalah grup properti tanpa ekspresi target terkait. - Jika
Imengidentifikasi variabel bersama dan tidak ada daftar argumen jenis yang disediakan, maka hasilnya adalah variabel atau nilai. Jika variabel bersifat baca-saja, dan referensi terjadi di luar konstruktor bersama dari jenis di mana variabel dideklarasikan, maka hasilnya adalah nilai variabelIbersama diE. Jika tidak, hasilnya adalah variabelIbersama diE. - Jika
Imengidentifikasi peristiwa bersama dan tidak ada daftar argumen jenis yang disediakan, hasilnya adalah akses peristiwa tanpa ekspresi target terkait. - Jika
Imengidentifikasi konstanta dan tidak ada daftar argumen jenis yang disediakan, maka hasilnya adalah nilai konstanta tersebut. - Jika
Imengidentifikasi anggota enumerasi dan tidak ada daftar argumen jenis yang disediakan, maka hasilnya adalah nilai anggota enumerasi tersebut. - Jika tidak,
E.Iadalah referensi anggota yang tidak valid, dan terjadi kesalahan waktu kompilasi.
- Jika
Jika
Ediklasifikasikan sebagai variabel atau nilai, jenisnya adalahT, maka pencarian anggota dilakukan dalam konteksT. JikaIadalah nama anggota yang dapat diakses dariT, makaE.Idievaluasi dan diklasifikasikan sebagai berikut:- Jika
Iadalah kata kunciNew,EadalahMe, ,MyBaseatauMyClass, dan tidak ada argumen jenis yang disediakan, maka hasilnya adalah grup metode yang mewakili konstruktor instans dari jenisEdengan ekspresi target terkait danEtidak ada daftar argumen jenis. Jika tidak, terjadi kesalahan waktu kompilasi. - Jika
Imengidentifikasi satu atau beberapa metode, termasuk metode ekstensi jikaTtidakObject, maka hasilnya adalah grup metode dengan daftar argumen jenis terkait dan ekspresi target terkait .E - Jika
Imengidentifikasi satu atau beberapa properti dan tidak ada argumen jenis yang disediakan, maka hasilnya adalah grup properti dengan ekspresi target terkait .E - Jika
Imengidentifikasi variabel bersama atau variabel instans dan tidak ada argumen jenis yang disediakan, maka hasilnya adalah variabel atau nilai. Jika variabel bersifat baca-saja, dan referensi terjadi di luar konstruktor kelas di mana variabel dinyatakan sesuai untuk jenis variabel (bersama atau instans), maka hasilnya adalah nilai variabelIdalam objek yang direferensikan olehE. JikaTadalah jenis referensi, maka hasilnya adalah variabelIdalam objek yang dirujuk olehE. Jika tidak, jikaTadalah jenis nilai dan ekspresiEdiklasifikasikan sebagai variabel, hasilnya adalah variabel; jika tidak, hasilnya adalah nilai. - Jika
Imengidentifikasi peristiwa dan tidak ada argumen jenis yang disediakan, hasilnya adalah akses peristiwa dengan ekspresi target terkait dariE. - Jika
Imengidentifikasi argumen konstanta dan tidak ada jenis yang disediakan, maka hasilnya adalah nilai konstanta tersebut. - Jika
Imengidentifikasi anggota enumerasi dan tidak ada argumen jenis yang disediakan, maka hasilnya adalah nilai anggota enumerasi tersebut. - Jika
TadalahObject, maka hasilnya adalah pencarian anggota yang terlambat terikat yang diklasifikasikan sebagai akses terikat terlambat dengan daftar argumen jenis terkait dan ekspresi target terkait dariE.
- Jika
Jika tidak,
E.Iadalah referensi anggota yang tidak valid, dan terjadi kesalahan waktu kompilasi.
Akses anggota formulir MyClass.I(Of A) setara dengan Me.I(Of A), tetapi semua anggota yang diakses di dalamnya diperlakukan seolah-olah anggota tidak dapat diambil alih. Dengan demikian, anggota yang diakses tidak akan terpengaruh oleh jenis run-time nilai tempat anggota diakses.
Akses anggota formulir MyBase.I(Of A) setara dengan CType(Me, T).I(Of A) di mana T adalah jenis dasar langsung dari jenis yang berisi ekspresi akses anggota. Semua pemanggilan metode di atasnya diperlakukan seolah-olah metode yang dipanggil tidak dapat diambil alih. Bentuk akses anggota ini juga disebut akses dasar.
Contoh berikut menunjukkan bagaimana Me, MyBase dan MyClass berhubungan:
Class Base
Public Overridable Sub F()
Console.WriteLine("Base.F")
End Sub
End Class
Class Derived
Inherits Base
Public Overrides Sub F()
Console.WriteLine("Derived.F")
End Sub
Public Sub G()
MyClass.F()
End Sub
End Class
Class MoreDerived
Inherits Derived
Public Overrides Sub F()
Console.WriteLine("MoreDerived.F")
End Sub
Public Sub H()
MyBase.F()
End Sub
End Class
Module Test
Sub Main()
Dim x As MoreDerived = new MoreDerived()
x.F()
x.G()
x.H()
End Sub
End Module
Kode ini mencetak:
MoreDerived.F
Derived.F
Derived.F
Ketika ekspresi akses anggota dimulai dengan kata kunci Global, kata kunci mewakili namespace layanan terluar yang tidak disebutkan namanya, yang berguna dalam situasi di mana deklarasi membayangi namespace yang merangkum. Kata Global kunci memungkinkan "melarikan diri" ke namespace terluar dalam situasi itu. Contohnya:
Class System
End Class
Module Test
Sub Main()
' Error: Class System does not contain Console
System.Console.WriteLine("Hello, world!")
' Legal, binds to System in outermost namespace
Global.System.Console.WriteLine("Hello, world!")
End Sub
End Module
Dalam contoh di atas, panggilan metode pertama tidak valid karena pengidentifikasi System mengikat ke kelas System, bukan namespace System. Satu-satunya System cara untuk mengakses namespace layanan adalah dengan menggunakan Global untuk keluar ke namespace layanan terluar.
Jika anggota yang diakses dibagikan, ekspresi apa pun di sisi kiri periode berlebihan dan tidak dievaluasi kecuali akses anggota dilakukan terlambat. Misalnya, pertimbangkan kode berikut:
Class C
Public Shared F As Integer = 10
End Class
Module Test
Public Function ReturnC() As C
Console.WriteLine("Returning a new instance of C.")
Return New C()
End Function
Public Sub Main()
Console.WriteLine("The value of F is: " & ReturnC().F)
End Sub
End Module
Ini dicetak The value of F is: 10 karena fungsi ReturnC tidak perlu dipanggil untuk menyediakan instans C untuk mengakses anggota Fbersama .
Tipe Identik dan Nama Anggota
Tidak jarang memberi nama anggota menggunakan nama yang sama dengan jenis mereka. Namun, dalam situasi itu, persembunyian nama yang tidak nyaman dapat terjadi:
Enum Color
Red
Green
Yellow
End Enum
Class Test
ReadOnly Property Color() As Color
Get
Return Color.Red
End Get
End Property
Shared Function DefaultColor() As Color
Return Color.Green ' Binds to the instance property!
End Function
End Class
Dalam contoh sebelumnya, nama Color sederhana dalam DefaultColor pengikatan ke properti instans alih-alih jenisnya. Karena anggota instans tidak dapat dirujuk dalam anggota bersama, biasanya ini akan menjadi kesalahan.
Namun, aturan khusus memungkinkan akses ke jenis dalam kasus ini. Jika ekspresi dasar ekspresi akses anggota adalah nama sederhana dan mengikat konstanta, bidang, properti, variabel lokal, atau parameter yang jenisnya memiliki nama yang sama, maka ekspresi dasar dapat merujuk ke anggota atau jenisnya. Ini tidak pernah dapat mengakibatkan ambiguitas karena anggota yang dapat diakses dari salah satu sama.
Instans Default
Dalam beberapa situasi, kelas yang berasal dari kelas dasar umum biasanya atau selalu hanya memiliki satu instans. Misalnya, sebagian besar jendela yang ditampilkan di antarmuka pengguna hanya pernah memiliki satu instans yang ditampilkan di layar kapan saja. Untuk menyederhanakan bekerja dengan jenis kelas ini, Visual Basic dapat secara otomatis menghasilkan instans default kelas yang menyediakan satu instans yang mudah direferensikan untuk setiap kelas.
Instans default selalu dibuat untuk keluarga jenis daripada untuk satu jenis tertentu. Jadi alih-alih membuat instans default untuk kelas Form1 yang berasal dari Formulir, instans default dibuat untuk semua kelas yang berasal dari Formulir. Ini berarti bahwa setiap kelas individu yang berasal dari kelas dasar tidak harus ditandai secara khusus untuk memiliki instans default.
Instans default kelas diwakili oleh properti yang dihasilkan kompilator yang mengembalikan instans default kelas tersebut. Properti yang dihasilkan sebagai anggota kelas yang disebut kelas grup yang mengelola alokasi dan menghancurkan instans default untuk semua kelas yang berasal dari kelas dasar tertentu. Misalnya, semua properti instans default kelas yang berasal dari Form dapat dikumpulkan di MyForms kelas . Jika instans kelas grup dikembalikan oleh ekspresi My.Forms, kode berikut mengakses instans default kelas Form1 turunan dan Form2:
Class Form1
Inherits Form
Public x As Integer
End Class
Class Form2
Inherits Form
Public y As Integer
End Class
Module Main
Sub Main()
My.Forms.Form1.x = 10
Console.WriteLine(My.Forms.Form2.y)
End Sub
End Module
Instans default tidak akan dibuat sampai referensi pertama ke instans tersebut; mengambil properti yang mewakili instans default menyebabkan instans default dibuat jika belum dibuat atau telah diatur ke Nothing. Untuk memungkinkan pengujian keberadaan instans default, ketika instans default adalah target Is operator atau IsNot , instans default tidak akan dibuat. Dengan demikian, dimungkinkan untuk menguji apakah instans default adalah Nothing atau beberapa referensi lain tanpa menyebabkan instans default dibuat.
Instans default dimaksudkan untuk memudahkan untuk merujuk ke instans default dari luar kelas yang memiliki instans default. Menggunakan instans default dari dalam kelas yang mendefinisikannya dapat menyebabkan kebingungan tentang instans mana yang dirujuk, yaitu instans default atau instans saat ini. Misalnya, kode berikut hanya memodifikasi nilai x dalam instans default, meskipun sedang dipanggil dari instans lain. Dengan demikian kode akan mencetak nilai 5 alih-alih 10:
Class Form1
Inherits Form
Public x As Integer = 5
Public Sub ChangeX()
Form1.x = 10
End Sub
End Class
Module Main
Sub Main()
Dim f As Form1 = New Form1()
f.ChangeX()
Console.WriteLine(f.x)
End Sub
End Module
Untuk mencegah kebingungan semacam ini, tidak valid untuk merujuk ke instans default dari dalam metode instans dari jenis instans default.
Instans Default dan Nama Jenis
Instans default juga dapat diakses langsung melalui nama jenisnya. Dalam hal ini, dalam konteks ekspresi apa pun di mana nama jenis tidak diizinkan ekspresi E, di mana E mewakili nama kelas yang sepenuhnya memenuhi syarat dengan instans default, diubah menjadi E', di mana E' mewakili ekspresi yang mengambil properti instans default. Misalnya, jika instans default untuk kelas yang berasal dari Form mengizinkan mengakses instans default melalui nama jenis, maka kode berikut setara dengan kode dalam contoh sebelumnya:
Module Main
Sub Main()
Form1.x = 10
Console.WriteLine(Form2.y)
End Sub
End Module
Ini juga berarti bahwa instans default yang dapat diakses melalui nama jenisnya juga dapat ditetapkan melalui nama jenis. Misalnya, kode berikut menetapkan instans default ke Form1Nothing:
Module Main
Sub Main()
Form1 = Nothing
End Sub
End Module
Perhatikan bahwa arti dari E.I itu E mewakili kelas dan I mewakili anggota bersama tidak berubah. Ekspresi seperti itu masih mengakses anggota bersama langsung dari instans kelas dan tidak mereferensikan instans default.
Kelas Grup
Atribut Microsoft.VisualBasic.MyGroupCollectionAttribute menunjukkan kelas grup untuk keluarga instans default. Atribut memiliki empat parameter:
Parameter
TypeToCollectmenentukan kelas dasar untuk grup. Semua kelas yang dapat dibuat tanpa parameter jenis terbuka yang berasal dari jenis dengan nama ini (terlepas dari parameter jenis) akan secara otomatis memiliki instans default.Parameter
CreateInstanceMethodNamemenentukan metode yang akan dipanggil di kelas grup untuk membuat instans baru di properti instans default.Parameter
DisposeInstanceMethodNamemenentukan metode untuk memanggil di kelas grup untuk membuang properti instans default jika properti instans default diberi nilaiNothing.Parameter
DefaultInstanceAliasmenspesifikasikan ekspresiE'untuk menggantikan nama kelas jika instans default dapat diakses langsung melalui nama jenisnya. Jika parameter ini adalahNothingatau string kosong, instans default pada jenis grup ini tidak dapat diakses langsung melalui nama jenisnya. (Catatan. Dalam semua implementasi bahasa Visual Basic saat ini,DefaultInstanceAliasparameter diabaikan, kecuali dalam kode yang disediakan kompilator.)
Beberapa jenis dapat dikumpulkan ke dalam grup yang sama dengan memisahkan nama jenis dan metode dalam tiga parameter pertama menggunakan koma. Harus ada jumlah item yang sama di setiap parameter, dan elemen daftar dicocokkan secara berurutan. Misalnya, deklarasi atribut berikut mengumpulkan jenis yang berasal dari C1, C2 atau C3 ke dalam satu grup:
<Microsoft.VisualBasic.MyGroupCollection("C1, C2, C3", _
"CreateC1, CreateC2, CreateC3", _
"DisposeC1, DisposeC2, DisposeC3", "My.Cs")>
Public NotInheritable Class MyCs
...
End Class
Tanda tangan metode buat harus dari formulir Shared Function <Name>(Of T As {New, <Type>})(Instance Of T) As T. Metode pembuangan harus dalam bentuk Shared Sub <Name>(Of T As <Type>)(ByRef Instance Of T). Dengan demikian, kelas grup untuk contoh di bagian sebelumnya dapat dinyatakan sebagai berikut:
<Microsoft.VisualBasic.MyGroupCollection("Form", "Create", _
"Dispose", "My.Forms")> _
Public NotInheritable Class MyForms
Private Shared Function Create(Of T As {New, Form}) _
(Instance As T) As T
If Instance Is Nothing Then
Return New T()
Else
Return Instance
End If
End Function
Private Shared Sub Dispose(Of T As Form)(ByRef Instance As T)
Instance.Close()
Instance = Nothing
End Sub
End Class
Jika file sumber mendeklarasikan kelas Form1turunan , kelas grup yang dihasilkan akan setara dengan:
<Microsoft.VisualBasic.MyGroupCollection("Form", "Create", _
"Dispose", "My.Forms")> _
Public NotInheritable Class MyForms
Private Shared Function Create(Of T As {New, Form}) _
(Instance As T) As T
If Instance Is Nothing Then
Return New T()
Else
Return Instance
End If
End Function
Private Shared Sub Dispose(Of T As Form)(ByRef Instance As T)
Instance.Close()
Instance = Nothing
End Sub
Private m_Form1 As Form1
Public Property Form1() As Form1
Get
Return Create(m_Form1)
End Get
Set (Value As Form1)
If Value IsNot Nothing AndAlso Value IsNot m_Form1 Then
Throw New ArgumentException( _
"Property can only be set to Nothing.")
End If
Dispose(m_Form1)
End Set
End Property
End Class
Kumpulan Metode Ekstensi
Metode ekstensi untuk ekspresi E.I akses anggota dikumpulkan dengan mengumpulkan semua metode ekstensi dengan nama I yang tersedia dalam konteks saat ini:
- Pertama, setiap jenis berlapis yang berisi ekspresi dicentang, mulai dari yang paling dalam dan masuk ke terluar.
- Kemudian, setiap namespace berlapis dicentang, mulai dari bagian dalam dan masuk ke namespace layanan terluar.
- Kemudian, impor dalam file sumber dicentang.
- Kemudian, impor yang ditentukan oleh lingkungan kompilasi diperiksa.
Metode ekstensi dikumpulkan hanya jika ada konversi asli yang melebar dari jenis ekspresi target ke jenis parameter pertama metode ekstensi. Dan tidak seperti pengikatan ekspresi nama sederhana biasa, pencarian mengumpulkan semua metode ekstensi; koleksi tidak berhenti ketika metode ekstensi ditemukan. 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 Double)
End Sub
End Module
End Namespace
Namespace N1.N2.N3
Module Test
Sub Main()
Dim x As New C1()
' Calls N1C1Extensions.M1
x.M1(10)
End Sub
End Module
End Namespace
Dalam contoh ini, meskipun N2C1Extensions.M1 ditemukan sebelumnya N1C1Extensions.M1, keduanya dianggap sebagai metode ekstensi. Setelah semua metode ekstensi dikumpulkan, metode tersebut kemudian dikuripsi. Currying mengambil target panggilan metode ekstensi dan menerapkannya ke panggilan metode ekstensi, menghasilkan tanda tangan metode baru dengan parameter pertama yang dihapus (karena telah ditentukan). Contohnya:
Imports System.Runtime.CompilerServices
Module Ext1
<Extension> _
Sub M(x As Integer, y As Integer)
End Sub
End Module
Module Ext2
<Extension> _
Sub M(x As Integer, y As Double)
End Sub
End Module
Module Main
Sub Test()
Dim v As Integer = 10
' The curried method signatures considered are:
' Ext1.M(y As Integer)
' Ext2.M(y As Double)
v.M(10)
End Sub
End Module
Dalam contoh di atas, hasil kurir dari penerapan vExt1.M adalah tanda tangan Sub M(y As Integer)metode .
Selain menghapus parameter pertama metode ekstensi, kari juga menghapus parameter jenis metode apa pun yang merupakan bagian dari jenis parameter pertama. Saat membuat kari metode ekstensi dengan parameter jenis metode, inferensi jenis diterapkan ke parameter pertama dan hasilnya diperbaiki untuk parameter jenis apa pun yang disimpulkan. Jika inferensi jenis gagal, metode diabaikan. Contohnya:
Imports System.Runtime.CompilerServices
Module Ext1
<Extension> _
Sub M(Of T, U)(x As T, y As U)
End Sub
End Module
Module Ext2
<Extension> _
Sub M(Of T)(x As T, y As T)
End Sub
End Module
Module Main
Sub Test()
Dim v As Integer = 10
' The curried method signatures considered are:
' Ext1.M(Of U)(y As U)
' Ext2.M(y As Integer)
v.M(10)
End Sub
End Module
Dalam contoh di atas, hasil kurir penerapan vExt1.M adalah tanda tangan Sub M(Of U)(y As U)metode , karena parameter T jenis disimpulkan sebagai akibat dari kari dan sekarang diperbaiki. Karena parameter U jenis tidak disimpulkan sebagai bagian dari kari, parameter tetap terbuka. Demikian pula, karena parameter T jenis disimpulkan sebagai akibat dari penerapan v ke Ext2.M, jenis parameter y menjadi tetap sebagai Integer. Ini tidak akan disimpulkan sebagai jenis lain. Saat mengkueri tanda tangan, semua batasan kecuali untuk New batasan juga diterapkan. Jika batasan tidak terpenuhi, atau bergantung pada jenis yang tidak disimpulkan sebagai bagian dari kari, metode ekstensi diabaikan. Contohnya:
Imports System.Runtime.CompilerServices
Module Ext1
<Extension> _
Sub M1(Of T As Structure)(x As T, y As Integer)
End Sub
<Extension> _
Sub M2(Of T As U, U)(x As T, y As U)
End Sub
End Module
Module Main
Sub Test()
Dim s As String = "abc"
' Error: String does not satisfy the Structure constraint
s.M1(10)
' Error: T depends on U, which cannot be inferred
s.M2(10)
End Sub
End Module
Nota. Salah satu alasan utama untuk melakukan kari metode ekstensi adalah memungkinkan ekspresi kueri menyimpulkan jenis iterasi sebelum mengevaluasi argumen ke metode pola kueri. Karena sebagian besar metode pola kueri mengambil ekspresi lambda, yang memerlukan inferensi jenis itu sendiri, ini sangat menyederhanakan proses evaluasi ekspresi kueri.
Tidak seperti pewarisan antarmuka normal, metode ekstensi yang memperluas dua antarmuka yang tidak berhubungan satu sama lain tersedia, selama mereka tidak memiliki tanda tangan kurir yang sama:
Imports System.Runtime.CompilerServices
Interface I1
End Interface
Interface I2
End Interface
Class C1
Implements I1, I2
End Class
Module I1Ext
<Extension> _
Sub M1(i As I1, x As Integer)
End Sub
<Extension> _
Sub M2(i As I1, x As Integer)
End Sub
End Module
Module I2Ext
<Extension> _
Sub M1(i As I2, x As Integer)
End Sub
<Extension> _
Sub M2(I As I2, x As Double)
End Sub
End Module
Module Main
Sub Test()
Dim c As New C1()
' Error: M is ambiguous between I1Ext.M1 and I2Ext.M1.
c.M1(10)
' Calls I1Ext.M2
c.M2(10)
End Sub
End Module
Terakhir, penting untuk diingat bahwa metode ekstensi tidak dipertimbangkan saat melakukan pengikatan terlambat:
Module Test
Sub Main()
Dim o As Object = ...
' Ignores extension methods
o.M1()
End Sub
End Module
Ekspresi Akses Anggota Kamus
Ekspresi akses anggota kamus digunakan untuk mencari anggota koleksi. Akses anggota kamus mengambil bentuk E!I, di mana E adalah ekspresi yang diklasifikasikan sebagai nilai dan I merupakan pengidentifikasi.
DictionaryAccessExpression
: Expression? '!' IdentifierOrKeyword
;
Jenis ekspresi harus memiliki properti default yang diindeks oleh satu String parameter. Ekspresi E!I akses anggota kamus diubah menjadi ekspresi E.D("I"), di mana D adalah properti default .E Contohnya:
Class Keys
Public ReadOnly Default Property Item(s As String) As Integer
Get
Return 10
End Get
End Property
End Class
Module Test
Sub Main()
Dim x As Keys = new Keys()
Dim y As Integer
' The two statements are equivalent.
y = x!abc
y = x("abc")
End Sub
End Module
Jika tanda seru ditentukan tanpa ekspresi, ekspresi dari pernyataan yang segera berisi With diasumsikan. Jika tidak ada pernyataan yang berisi With , kesalahan waktu kompilasi terjadi.
Ekspresi Pemanggilan
Ekspresi pemanggilan terdiri dari target pemanggilan dan daftar argumen opsional.
InvocationExpression
: Expression ( OpenParenthesis ArgumentList? CloseParenthesis )?
;
ArgumentList
: PositionalArgumentList
| PositionalArgumentList Comma NamedArgumentList
| NamedArgumentList
;
PositionalArgumentList
: Expression? ( Comma Expression? )*
;
NamedArgumentList
: IdentifierOrKeyword ColonEquals Expression
( Comma IdentifierOrKeyword ColonEquals Expression )*
;
Ekspresi target harus diklasifikasikan sebagai grup metode atau nilai yang jenisnya adalah jenis delegasi. Jika ekspresi target adalah nilai yang jenisnya adalah jenis delegasi, maka target ekspresi pemanggilan menjadi grup metode untuk Invoke anggota jenis delegasi dan ekspresi target menjadi ekspresi target terkait dari grup metode.
Daftar argumen memiliki dua bagian: argumen posisi dan argumen bernama.
Argumen posisi adalah ekspresi dan harus mendahului argumen bernama apa pun.
Argumen bernama dimulai dengan pengidentifikasi yang dapat mencocokkan kata kunci, diikuti oleh := dan ekspresi.
Jika grup metode hanya berisi satu metode yang dapat diakses, termasuk metode instans dan ekstensi, dan metode tersebut tidak mengambil argumen dan merupakan fungsi, maka grup metode ditafsirkan sebagai ekspresi pemanggilan dengan daftar argumen kosong dan hasilnya digunakan sebagai target ekspresi pemanggilan dengan daftar argumen yang disediakan. Contohnya:
Class C1
Function M1() As Integer()
Return New Integer() { 1, 2, 3 }
End Sub
End Class
Module Test
Sub Main()
Dim c As New C1()
' Prints 3
Console.WriteLine(c.M1(2))
End Sub
End Module
Jika tidak, resolusi kelebihan beban diterapkan ke metode untuk memilih metode yang paling berlaku untuk daftar argumen yang diberikan. Jika metode yang paling berlaku adalah fungsi, maka hasil ekspresi pemanggilan diklasifikasikan sebagai nilai yang ditik sebagai jenis pengembalian fungsi. Jika metode yang paling berlaku adalah subroutine, maka hasilnya diklasifikasikan sebagai batal. Jika metode yang paling berlaku adalah metode parsial yang tidak memiliki isi, maka ekspresi pemanggilan diabaikan dan hasilnya diklasifikasikan sebagai batal.
Untuk ekspresi pemanggilan terikat awal, argumen dievaluasi dalam urutan di mana parameter yang sesuai dideklarasikan dalam metode target. Untuk ekspresi akses anggota yang terlambat terikat, mereka dievaluasi dalam urutan muncul dalam ekspresi akses anggota: lihat Bagian Late-Bound Ekspresi.
Resolusi Metode Kelebihan Beban:
Untuk Resolusi Kelebihan Beban, Kekhususan anggota/jenis yang diberi daftar argumen, Generikitas, Penerapan ke Daftar Argumen, Argumen Meneruskan, dan Memilih Argumen untuk Parameter Opsional, Metode Bersyarah, dan Inferensi Argumen Jenis: lihat Bagian Resolusi Kelebihan Beban.
Ekspresi Indeks
Ekspresi indeks menghasilkan elemen array atau mengklasifikasikan ulang grup properti ke dalam akses properti. Ekspresi indeks terdiri dari, dalam urutan, ekspresi, tanda kurung pembuka, daftar argumen indeks, dan tanda kurung penutup.
IndexExpression
: Expression OpenParenthesis ArgumentList? CloseParenthesis
;
Target ekspresi indeks harus diklasifikasikan sebagai grup properti atau nilai. Ekspresi indeks diproses sebagai berikut:
Jika ekspresi target diklasifikasikan sebagai nilai dan jika jenisnya bukan jenis array,
Object, atauSystem.Array, jenis harus memiliki properti default. Indeks dilakukan pada grup properti yang mewakili semua properti default jenis. Meskipun tidak valid untuk mendeklarasikan properti default tanpa parameter di Visual Basic, bahasa lain mungkin memungkinkan mendeklarasikan properti tersebut. Akibatnya, mengindeks properti tanpa argumen diizinkan.Jika ekspresi menghasilkan nilai jenis array, jumlah argumen dalam daftar argumen harus sama dengan peringkat jenis array dan mungkin tidak menyertakan argumen bernama. Jika salah satu indeks tidak valid pada waktu proses,
System.IndexOutOfRangeExceptionpengecualian akan dilemparkan. Setiap ekspresi harus secara implisit dapat dikonversi ke jenisInteger. Hasil ekspresi indeks adalah variabel pada indeks yang ditentukan dan diklasifikasikan sebagai variabel.Jika ekspresi diklasifikasikan sebagai grup properti, resolusi kelebihan beban digunakan untuk menentukan apakah salah satu properti berlaku untuk daftar argumen indeks. Jika grup properti hanya berisi satu properti yang memiliki
Getpengakses dan jika aksesor tersebut tidak mengambil argumen, maka grup properti ditafsirkan sebagai ekspresi indeks dengan daftar argumen kosong. Hasilnya digunakan sebagai target ekspresi indeks saat ini. Jika tidak ada properti yang berlaku, maka terjadi kesalahan waktu kompilasi. Jika tidak, ekspresi menghasilkan akses properti dengan ekspresi target terkait (jika ada) dari grup properti.Jika ekspresi diklasifikasikan sebagai grup properti yang terlambat terikat atau sebagai nilai yang jenisnya adalah
ObjectatauSystem.Array, pemrosesan ekspresi indeks ditangguhkan hingga run time dan pengindeksan terlambat terikat. Ekspresi menghasilkan akses properti yang terlambat terikat yang di ketik sebagaiObject. Ekspresi target terkait adalah ekspresi target, jika merupakan nilai, atau ekspresi target terkait dari grup properti. Pada waktu proses ekspresi diproses sebagai berikut:Jika ekspresi diklasifikasikan sebagai grup properti yang terlambat terikat, ekspresi dapat mengakibatkan grup metode, grup properti, atau nilai (jika anggota adalah instans atau variabel bersama). Jika hasilnya adalah grup metode atau grup properti, resolusi kelebihan beban diterapkan ke grup untuk menentukan metode yang benar untuk daftar argumen. Jika resolusi kelebihan beban gagal,
System.Reflection.AmbiguousMatchExceptionpengecualian akan dilemparkan. Kemudian hasilnya diproses baik sebagai akses properti atau sebagai pemanggilan dan hasilnya dikembalikan. Jika pemanggilan adalah subroutine, hasilnya adalahNothing.Jika jenis run-time ekspresi target adalah jenis array atau
System.Array, hasil ekspresi indeks adalah nilai variabel pada indeks yang ditentukan.Jika tidak, jenis run-time ekspresi harus memiliki properti default dan indeks dilakukan pada grup properti yang mewakili semua properti default pada jenis . Jika jenis tidak memiliki properti default, maka
System.MissingMemberExceptionpengecualian akan dilemparkan.
Ekspresi Baru
Operator New digunakan untuk membuat instans jenis baru. Ada empat bentuk New ekspresi:
Ekspresi pembuatan objek digunakan untuk membuat instans baru jenis kelas dan jenis nilai.
Ekspresi pembuatan array digunakan untuk membuat instans baru dari jenis array.
Ekspresi pembuatan delegasi (yang tidak memiliki sintaks yang berbeda dari ekspresi pembuatan objek) digunakan untuk membuat instans baru jenis delegasi.
Ekspresi pembuatan objek anonim digunakan untuk membuat instans baru jenis kelas anonim.
NewExpression
: ObjectCreationExpression
| ArrayExpression
| AnonymousObjectCreationExpression
;
Ekspresi New diklasifikasikan sebagai nilai dan hasilnya adalah instans baru dari jenis tersebut.
Ekspresi Object-Creation
Ekspresi pembuatan objek digunakan untuk membuat instans baru dari jenis kelas atau jenis struktur.
ObjectCreationExpression
: 'New' NonArrayTypeName ( OpenParenthesis ArgumentList? CloseParenthesis )?
ObjectCreationExpressionInitializer?
;
ObjectCreationExpressionInitializer
: ObjectMemberInitializer
| ObjectCollectionInitializer
;
ObjectMemberInitializer
: 'With' OpenCurlyBrace FieldInitializerList CloseCurlyBrace
;
FieldInitializerList
: FieldInitializer ( Comma FieldInitializer )*
;
FieldInitializer
: 'Key'? ('.' IdentifierOrKeyword Equals )? Expression
;
ObjectCollectionInitializer
: 'From' CollectionInitializer
;
CollectionInitializer
: OpenCurlyBrace CollectionElementList? CloseCurlyBrace
;
CollectionElementList
: CollectionElement ( Comma CollectionElement )*
;
CollectionElement
: Expression
| CollectionInitializer
;
Jenis ekspresi pembuatan objek harus merupakan jenis kelas, jenis struktur, atau parameter jenis dengan New batasan dan tidak dapat menjadi MustInherit kelas. Mengingat ekspresi pembuatan objek formulir New T(A), di mana T adalah jenis kelas atau jenis struktur dan A merupakan daftar argumen opsional, resolusi kelebihan beban menentukan konstruktor yang benar untuk T memanggil. Parameter jenis dengan New batasan dianggap memiliki satu konstruktor tanpa parameter. Jika tidak ada konstruktor yang dapat dipanggil, kesalahan waktu kompilasi terjadi; jika tidak, ekspresi menghasilkan pembuatan instans baru menggunakan T konstruktor yang dipilih. Jika tidak ada argumen, tanda kurung mungkin dihilangkan.
Di mana instans dialokasikan tergantung pada apakah instans adalah jenis kelas atau jenis nilai.
New instans jenis kelas dibuat pada timbunan sistem, sementara instans baru jenis nilai dibuat langsung pada tumpukan.
Ekspresi pembuatan objek dapat secara opsional menentukan daftar inisialisasi anggota setelah argumen konstruktor. Penginisialisasi anggota ini diawali dengan kata kunci With, dan daftar penginisialisasi ditafsirkan seolah-olah itu dalam konteks With pernyataan. Misalnya, mengingat kelas:
Class Customer
Dim Name As String
Dim Address As String
End Class
Kode:
Module Test
Sub Main()
Dim x As New Customer() With { .Name = "Bob Smith", _
.Address = "123 Main St." }
End Sub
End Module
Kira-kira setara dengan:
Module Test
Sub Main()
Dim x, _t1 As Customer
_t1 = New Customer()
With _t1
.Name = "Bob Smith"
.Address = "123 Main St."
End With
x = _t1
End Sub
End Module
Setiap penginisialisasi harus menentukan nama yang akan ditetapkan, dan nama harus berupa variabel non-instansReadOnly atau properti dari jenis yang sedang dibangun; akses anggota tidak akan terlambat terikat jika jenis yang sedang dibangun adalah Object. Penginisialisasi mungkin tidak menggunakan Key kata kunci. Setiap anggota dalam jenis hanya dapat diinisialisasi sekali. Namun, ekspresi penginisialisasi dapat saling merujuk. Contohnya:
Module Test
Sub Main()
Dim x As New Customer() With { .Name = "Bob Smith", _
.Address = .Name & " St." }
End Sub
End Module
Penginisialisasi ditetapkan kiri-ke-kanan, jadi jika penginisialisasi mengacu pada anggota yang belum diinisialisasi, itu akan melihat nilai apa pun variabel instans setelah konstruktor berjalan:
Module Test
Sub Main()
' The value of Address will be " St." since Name has not been
' assigned yet.
Dim x As New Customer() With { .Address = .Name & " St." }
End Sub
End Module
Penginisialisasi dapat ditumpuk:
Class Customer
Dim Name As String
Dim Address As Address
Dim Age As Integer
End Class
Class Address
Dim Street As String
Dim City As String
Dim State As String
Dim ZIP As String
End Class
Module Test
Sub Main()
Dim c As New Customer() With { _
.Name = "John Smith", _
.Address = New Address() With { _
.Street = "23 Main St.", _
.City = "Peoria", _
.State = "IL", _
.ZIP = "13934" }, _
.Age = 34 }
End Sub
End Module
Jika jenis yang dibuat adalah jenis koleksi dan memiliki metode instans bernama Add (termasuk metode ekstensi dan metode bersama), maka ekspresi pembuatan objek dapat menentukan penginisialisasi koleksi yang diawali dengan kata kunci From. Ekspresi pembuatan objek tidak dapat menentukan penginisialisasi anggota dan penginisialisasi koleksi. Setiap elemen dalam penginisialisasi koleksi diteruskan sebagai argumen untuk pemanggilan Add fungsi. Contohnya:
Dim list = New List(Of Integer)() From { 1, 2, 3, 4 }
setara dengan:
Dim list = New List(Of Integer)()
list.Add(1)
list.Add(2)
list.Add(3)
Jika elemen adalah penginisialisasi koleksi itu sendiri, setiap elemen penginisialisasi sub-koleksi akan diteruskan sebagai argumen individual ke Add fungsi. Misalnya, berikut ini:
Dim dict = Dictionary(Of Integer, String) From { { 1, "One" },{ 2, "Two" } }
setara dengan:
Dim dict = New Dictionary(Of Integer, String)
dict.Add(1, "One")
dict.Add(2, "Two")
Ekspansi ini selalu dilakukan dan hanya pernah dilakukan satu tingkat dalam; setelah itu, sub-inisialisasi dianggap sebagai literal array. Contohnya:
' Error: List(Of T) does not have an Add method that takes two parameters.
Dim list = New List(Of Integer())() From { { 1, 2 }, { 3, 4 } }
' OK, this initializes the dictionary with (Integer, Integer()) pairs.
Dim dict = New Dictionary(Of Integer, Integer())() From _
{ { 1, { 2, 3 } }, { 3, { 4, 5 } } }
Ekspresi Array
Ekspresi array digunakan untuk membuat instans baru dari jenis array. Ada dua jenis ekspresi array: ekspresi pembuatan array, dan literal array.
Ekspresi pembuatan array
Jika pengubah inisialisasi ukuran array disediakan, jenis array yang dihasilkan diturunkan dengan menghapus masing-masing argumen individual dari daftar argumen inisialisasi ukuran array. Nilai setiap argumen menentukan batas atas dimensi yang sesuai dalam instans array yang baru dialokasikan. Jika ekspresi memiliki penginisialisasi koleksi yang tidak kosong, setiap argumen dalam daftar argumen harus berupa konstanta, dan panjang peringkat dan dimensi yang ditentukan oleh daftar ekspresi harus cocok dengan penginisialisasi koleksi.
Dim a() As Integer = New Integer(2) {}
Dim b() As Integer = New Integer(2) { 1, 2, 3 }
Dim c(,) As Integer = New Integer(1, 2) { { 1, 2, 3 } , { 4, 5, 6 } }
' Error, length/initializer mismatch.
Dim d() As Integer = New Integer(2) { 0, 1, 2, 3 }
Jika pengubah inisialisasi ukuran array tidak disediakan, maka nama jenis harus merupakan jenis array dan penginisialisasi koleksi harus kosong atau memiliki jumlah tingkat bersarang yang sama dengan peringkat jenis array yang ditentukan. Semua elemen dalam tingkat bersarang paling dalam harus secara implisit dapat dikonversi ke jenis elemen array dan harus diklasifikasikan sebagai nilai. Jumlah elemen di setiap penginisialisasi koleksi berlapis harus selalu konsisten dengan ukuran koleksi lain pada tingkat yang sama. Panjang dimensi individual disimpulkan dari jumlah elemen di setiap tingkat berlapis penginisialisasi koleksi yang sesuai. Jika penginisialisasi koleksi kosong, panjang setiap dimensi adalah nol.
Dim e() As Integer = New Integer() { 1, 2, 3 }
Dim f(,) As Integer = New Integer(,) { { 1, 2, 3 } , { 4, 5, 6 } }
' Error: Inconsistent numbers of elements!
Dim g(,) As Integer = New Integer(,) { { 1, 2 }, { 4, 5, 6 } }
' Error: Inconsistent levels of nesting!
Dim h(,) As Integer = New Integer(,) { 1, 2, { 3, 4 } }
Tingkat berlapis terluar dari penginisialisasi koleksi sesuai dengan dimensi paling kiri array, dan tingkat berlapis terdahulu sesuai dengan dimensi paling kanan. Contohnya:
Dim array As Integer(,) = _
{ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, { 8, 9 } }
Setara dengan yang berikut ini:
Dim array(4, 1) As Integer
array(0, 0) = 0: array(0, 1) = 1
array(1, 0) = 2: array(1, 1) = 3
array(2, 0) = 4: array(2, 1) = 5
array(3, 0) = 6: array(3, 1) = 7
array(4, 0) = 8: array(4, 1) = 9
Jika penginisialisasi koleksi kosong (yaitu, yang berisi kurung kurawal tetapi tidak ada daftar inisialisasi) dan batas dimensi array yang diinisialisasi diketahui, penginisialisasi koleksi kosong mewakili instans array dari ukuran yang ditentukan di mana semua elemen telah diinisialisasi ke nilai default jenis elemen. Jika batas dimensi array yang diinisialisasi tidak diketahui, penginisialisasi koleksi kosong mewakili instans array di mana semua dimensi berukuran nol.
Peringkat dan panjang instans array dari setiap dimensi konstan untuk seluruh masa pakai instans. Dengan kata lain, tidak dimungkinkan untuk mengubah peringkat instans array yang ada, juga tidak mungkin untuk mengubah ukuran dimensinya.
Array Literals
Array secara harfiah menunjukkan array yang jenis elemen, peringkat, dan batasnya disimpulkan dari kombinasi konteks ekspresi dan penginisialisasi koleksi. Ini dijelaskan dalam Reklasifikasi Ekspresi Bagian.
ArrayExpression
: ArrayCreationExpression
| ArrayLiteralExpression
;
ArrayCreationExpression
: 'New' NonArrayTypeName ArrayNameModifier CollectionInitializer
;
ArrayLiteralExpression
: CollectionInitializer
;
Contohnya:
' array of integers
Dim a = {1, 2, 3}
' array of shorts
Dim b = {1S, 2S, 3S}
' array of shorts whose type is taken from the context
Dim c As Short() = {1, 2, 3}
' array of type Integer(,)
Dim d = {{1, 0}, {0, 1}}
' jagged array of rank ()()
Dim e = {({1, 0}), ({0, 1})}
' error: inconsistent rank
Dim f = {{1}, {2, 3}}
' error: inconsistent rank
Dim g = {1, {2}}
Format dan persyaratan untuk penginisialisasi koleksi dalam array literal sama persis dengan yang untuk penginisialisasi koleksi dalam ekspresi pembuatan array.
Nota. Array harfiah tidak membuat array di dalam dan dari dirinya sendiri; sebaliknya, ini adalah reklasifikasi ekspresi ke dalam nilai yang menyebabkan array dibuat. Misalnya, konversi CType(new Integer() {1,2,3}, Short()) tidak dimungkinkan karena tidak ada konversi dari Integer() ke Short(); tetapi ekspresi CType({1,2,3},Short()) dimungkinkan karena pertama kali mengklasifikasikan ulang array secara harfiah ke dalam ekspresi New Short() {1,2,3}pembuatan array .
Ekspresi Delegate-Creation
Ekspresi pembuatan delegasi digunakan untuk membuat instans baru dari jenis delegasi. Argumen ekspresi pembuatan delegasi harus berupa ekspresi yang diklasifikasikan sebagai penunjuk metode atau metode lambda.
Jika argumen adalah penunjuk metode, salah satu metode yang direferensikan oleh penunjuk metode harus berlaku untuk tanda tangan jenis delegasi. Metode M berlaku untuk jenis D delegasi jika:
MtidakPartialatau memiliki tubuh.Keduanya
MdanDmerupakan fungsi, atauDmerupakan subroutine.MdanDmemiliki jumlah parameter yang sama.Jenis
Mparameter masing-masing memiliki konversi dari jenis jenis parameter yang sesuai dariD, dan pengubahnya (yaituByRef,ByVal) cocok.Jenis pengembalian ,
Mjika ada, memiliki konversi ke jenis pengembalian .D
Jika penunjuk metode mereferensikan akses terikat terlambat, maka akses terikat terlambat diasumsikan ke fungsi yang memiliki jumlah parameter yang sama dengan jenis delegasi.
Jika semantik ketat tidak digunakan dan hanya ada satu metode yang direferensikan oleh penunjuk metode, tetapi tidak berlaku karena fakta bahwa ia tidak memiliki parameter dan jenis delegasi tidak, maka metode dianggap berlaku dan parameter atau nilai pengembalian hanya diabaikan. Contohnya:
Delegate Sub F(x As Integer)
Module Test
Sub M()
End Sub
Sub Main()
' Valid
Dim x As F = AddressOf M
End Sub
End Module
Nota. Relaksasi ini hanya diperbolehkan ketika semantik ketat tidak digunakan karena metode ekstensi. Karena metode ekstensi hanya dipertimbangkan jika metode reguler tidak berlaku, dimungkinkan untuk metode instans tanpa parameter untuk menyembunyikan metode ekstensi dengan parameter untuk tujuan mendelegasikan konstruksi.
Jika lebih dari satu metode yang direferensikan oleh penunjuk metode berlaku untuk jenis delegasi, maka resolusi kelebihan beban digunakan untuk memilih antara metode kandidat. Jenis parameter untuk delegasi digunakan sebagai jenis argumen untuk tujuan resolusi kelebihan beban. Jika tidak ada kandidat metode yang paling berlaku, kesalahan waktu kompilasi terjadi. Dalam contoh berikut, variabel lokal diinisialisasi dengan delegasi yang mengacu pada metode kedua Square karena metode tersebut lebih berlaku untuk tanda tangan dan mengembalikan jenis DoubleFunc.
Delegate Function DoubleFunc(x As Double) As Double
Module Test
Function Square(x As Single) As Single
Return x * x
End Function
Function Square(x As Double) As Double
Return x * x
End Function
Sub Main()
Dim a As New DoubleFunc(AddressOf Square)
End Sub
End Module
Jika metode kedua Square tidak ada, metode pertama Square akan dipilih. Jika semantik ketat ditentukan oleh lingkungan kompilasi atau oleh Option Strict, maka kesalahan waktu kompilasi terjadi jika metode yang paling spesifik yang direferensikan oleh penunjuk metode lebih sempit daripada tanda tangan delegasi. Metode M dianggap lebih sempit daripada jenis D delegasi jika:
Jenis
Mparameter memiliki konversi yang melebar ke jenis parameter yang sesuai dariD.Atau, jenis pengembalian, jika ada, dari
Mmemiliki konversi yang mempersempit ke jenis pengembalian .D
Jika argumen jenis dikaitkan dengan penunjuk metode, hanya metode dengan jumlah argumen jenis yang sama yang dipertimbangkan. Jika tidak ada argumen jenis yang terkait dengan penunjuk metode, inferensi jenis digunakan saat mencocokkan tanda tangan terhadap metode generik. Tidak seperti inferensi jenis normal lainnya, jenis pengembalian delegasi digunakan saat menyimpulkan argumen jenis, tetapi jenis pengembalian masih tidak dipertimbangkan saat menentukan kelebihan umum paling sedikit. Contoh berikut menunjukkan kedua cara menyediakan argumen jenis ke ekspresi pembuatan delegasi:
Delegate Function D(s As String, i As Integer) As Integer
Delegate Function E() As Integer
Module Test
Public Function F(Of T)(s As String, t1 As T) As T
End Function
Public Function G(Of T)() As T
End Function
Sub Main()
Dim d1 As D = AddressOf f(Of Integer) ' OK, type arg explicit
Dim d2 As D = AddressOf f ' OK, type arg inferred
Dim e1 As E = AddressOf g(Of Integer) ' OK, type arg explicit
Dim e2 As E = AddressOf g ' OK, infer from return
End Sub
End Module
Dalam contoh di atas, jenis delegasi non-generik dibuat menggunakan metode generik. Dimungkinkan juga untuk membuat instans jenis delegasi yang dibangun menggunakan metode generik. Contohnya:
Delegate Function Predicate(Of U)(u1 As U, u2 As U) As Boolean
Module Test
Function Compare(Of T)(t1 As List(of T), t2 As List(of T)) As Boolean
...
End Function
Sub Main()
Dim p As Predicate(Of List(Of Integer))
p = AddressOf Compare(Of Integer)
End Sub
End Module
Jika argumen untuk ekspresi pembuatan delegasi adalah metode lambda, metode lambda harus berlaku untuk tanda tangan jenis delegasi. Metode lambda L berlaku untuk jenis D delegasi jika:
Jika
Lmemiliki parameter,Dmemiliki jumlah parameter yang sama. (JikaLtidak memiliki parameter, parameterDdiabaikan.)Jenis
Lparameter masing-masing memiliki konversi ke jenis jenis parameter yang sesuai dariD, dan pengubahnya (yaituByRef,ByVal) cocok.Jika
Dadalah fungsi, jenisLpengembalian memiliki konversi ke jenis pengembalian .D(JikaDmerupakan subroutine, nilaiLpengembalian diabaikan.)
Jika jenis parameter parameter L dihilangkan, maka jenis parameter yang sesuai disimpulkan D ; jika parameter L memiliki pengubah nama array atau nullable, hasil kesalahan waktu kompilasi. Setelah semua jenis L parameter tersedia, maka jenis ekspresi dalam metode lambda disimpulkan. Contohnya:
Delegate Function F(x As Integer, y As Long) As Long
Module Test
Sub Main()
' b inferred to Integer, c and return type inferred to Long
Dim a As F = Function(b, c) b + c
' e and return type inferred to Integer, f inferred to Long
Dim d As F = Function(e, f) e + CInt(f)
End Sub
End Module
Dalam beberapa situasi di mana mendelegasikan tanda tangan tidak sama persis dengan metode lambda atau tanda tangan metode, .NET Framework mungkin tidak mendukung pembuatan delegasi secara asli. Dalam situasi itu, ekspresi metode lambda digunakan untuk mencocokkan dua metode. Contohnya:
Delegate Function IntFunc(x As Integer) As Integer
Module Test
Function SquareString(x As String) As String
Return CInt(x) * CInt(x)
End Function
Sub Main()
' The following two lines are equivalent
Dim a As New IntFunc(AddressOf SquareString)
Dim b As New IntFunc( _
Function(x As Integer) CInt(SquareString(CStr(x))))
End Sub
End Module
Hasil ekspresi pembuatan delegasi adalah instans delegasi yang mengacu pada metode pencocokan dengan ekspresi target terkait (jika ada) dari ekspresi penunjuk metode. Jika ekspresi target diketik sebagai jenis nilai, maka jenis nilai disalin ke timbunan sistem karena delegasi hanya dapat menunjuk ke metode objek pada tumpukan. Metode dan objek yang dirujuk delegasi tetap konstan selama seluruh masa pakai delegasi. Dengan kata lain, tidak dimungkinkan untuk mengubah target atau objek delegasi setelah dibuat.
Ekspresi Object-Creation Anonim
Ekspresi pembuatan objek dengan inisialisasi anggota juga dapat menghilangkan nama jenis sepenuhnya.
AnonymousObjectCreationExpression
: 'New' ObjectMemberInitializer
;
Dalam hal ini, jenis anonim dibangun berdasarkan jenis dan nama anggota yang diinisialisasi sebagai bagian dari ekspresi. Contohnya:
Module Test
Sub Main()
Dim Customer = New With { .Name = "John Smith", .Age = 34 }
Console.WriteLine(Customer.Name)
End Sub
End Module
Jenis yang dibuat oleh ekspresi pembuatan objek anonim adalah kelas yang tidak memiliki nama, mewarisi langsung dari Object, dan memiliki sekumpulan properti dengan nama yang sama dengan anggota yang ditetapkan dalam daftar inisialisasi anggota. Jenis setiap properti disimpulkan menggunakan aturan yang sama dengan inferensi jenis variabel lokal. Jenis anonim yang dihasilkan juga mengambil alih ToString, mengembalikan representasi string dari semua anggota dan nilainya. (Format yang tepat dari string ini berada di luar cakupan spesifikasi ini).
Secara default, properti yang dihasilkan oleh jenis anonim adalah baca-tulis. Dimungkinkan untuk menandai properti jenis anonim sebagai baca-saja dengan menggunakan pengubah Key . Pengubah Key menentukan bahwa bidang dapat digunakan untuk mengidentifikasi nilai yang diwakili oleh jenis anonim secara unik. Selain membuat properti baca-saja, hal ini juga menyebabkan jenis anonim mengambil alih Equals dan GetHashCode dan mengimplementasikan antarmuka System.IEquatable(Of T) (mengisi jenis anonim untuk T). Anggota didefinisikan sebagai berikut:
Function Equals(obj As Object) As Boolean dan Function Equals(val As T) As Boolean diimplementasikan dengan memvalidasi bahwa dua instans tersebut memiliki jenis yang sama dan kemudian membandingkan setiap Key anggota menggunakan Object.Equals. Jika semua Key anggota sama, maka Equals mengembalikan True, jika tidak Equals , mengembalikan False.
Function GetHashCode() As Integer diimplementasikan sedih sehingga jika Equals benar untuk dua instans jenis anonim, maka GetHashCode akan mengembalikan nilai yang sama. Hash dimulai dengan nilai awal dan kemudian, untuk setiap Key anggota, untuk mengalikan hash dengan 31 dan menambahkan Key nilai hash anggota (disediakan oleh GetHashCode) jika anggota bukan jenis referensi atau jenis nilai nullable dengan nilai Nothing.
Misalnya, jenis yang dibuat dalam pernyataan:
Dim zipState = New With { Key .ZipCode = 98112, .State = "WA" }
membuat kelas yang terlihat kira-kira seperti ini (meskipun implementasi yang tepat dapat bervariasi):
Friend NotInheritable Class $Anonymous1
Implements IEquatable(Of $Anonymous1)
Private ReadOnly _zipCode As Integer
Private _state As String
Public Sub New(zipCode As Integer, state As String)
_zipCode = zipcode
_state = state
End Sub
Public ReadOnly Property ZipCode As Integer
Get
Return _zipCode
End Get
End Property
Public Property State As String
Get
Return _state
End Get
Set (value As Integer)
_state = value
End Set
End Property
Public Overrides Function Equals(obj As Object) As Boolean
Dim val As $Anonymous1 = TryCast(obj, $Anonymous1)
Return Equals(val)
End Function
Public Overloads Function Equals(val As $Anonymous1) As Boolean _
Implements IEquatable(Of $Anonymous1).Equals
If val Is Nothing Then
Return False
End If
If Not Object.Equals(_zipCode, val._zipCode) Then
Return False
End If
Return True
End Function
Public Overrides Function GetHashCode() As Integer
Dim hash As Integer = 0
hash = hash Xor _zipCode.GetHashCode()
Return hash
End Function
Public Overrides Function ToString() As String
Return "{ Key .ZipCode = " & _zipCode & ", .State = " & _state & " }"
End Function
End Class
Untuk menyederhanakan situasi di mana jenis anonim dibuat dari bidang jenis lain, nama bidang dapat disimpulkan langsung dari ekspresi dalam kasus berikut:
Ekspresi
xnama sederhana menyimpulkan namax.Ekspresi
x.yakses anggota menyimpulkan namay.Ekspresi
x!ypencarian kamus menyimpulkan namay.Pemanggilan atau ekspresi indeks tanpa argumen
x()menyimpulkan namax.Ekspresi
x.<y>akses anggota XML ,x...<y>,x.@ymenyimpulkan namay.Ekspresi akses anggota XML yang merupakan target ekspresi
x.<y>.zakses anggota menyimpulkan namaz.Ekspresi akses anggota XML yang merupakan target pemanggilan atau ekspresi indeks tanpa argumen
x.<y>.z()menyimpulkan namaz.Ekspresi akses anggota XML yang merupakan target pemanggilan atau ekspresi
x.<y>(0)indeks menyimpulkan namay.
Penginisialisasi ditafsirkan sebagai penetapan ekspresi ke nama yang disimpulkan. Misalnya, penginisialisasi berikut setara:
Class Address
Public Street As String
Public City As String
Public State As String
Public ZIP As String
End Class
Class C1
Sub Test(a As Address)
Dim cityState1 = New With { .City = a.City, .State = a.State }
Dim cityState2 = New With { a.City, a.State }
End Sub
End Class
Jika nama anggota disimpulkan bahwa bertentangan dengan anggota jenis yang ada, seperti GetHashCode, maka kesalahan waktu kompilasi terjadi. Tidak seperti penginisialisasi anggota biasa, ekspresi pembuatan objek anonim tidak memungkinkan penginisialisasi anggota memiliki referensi melingkar, atau untuk merujuk ke anggota sebelum diinisialisasi. Contohnya:
Module Test
Sub Main()
' Error: Circular references
Dim x = New With { .a = .b, .b = .a }
' Error: Referring to .b before it has been assigned to
Dim y = New With { .a = .b, .b = 10 }
' Error: Referring to .a before it has been assigned to
Dim z = New With { .a = .a }
End Sub
End Module
Jika dua ekspresi pembuatan kelas anonim terjadi dalam metode yang sama dan menghasilkan bentuk yang dihasilkan yang sama -- jika urutan properti, nama properti, dan jenis properti semuanya cocok -- keduanya akan merujuk ke kelas anonim yang sama. Cakupan metode instans atau variabel anggota bersama dengan penginisialisasi adalah konstruktor tempat variabel diinisialisasi.
Nota. Ada kemungkinan bahwa kompilator dapat memilih untuk menyatukan jenis anonim lebih lanjut, seperti pada tingkat perakitan, tetapi ini tidak dapat diandalkan saat ini.
Ekspresi Pemeran
Ekspresi cast memaksa ekspresi ke jenis tertentu. Kata kunci cast tertentu memaksa ekspresi ke dalam jenis primitif. Tiga kata kunci pemeran umum, CType, TryCast dan DirectCast, memaksa ekspresi menjadi jenis.
CastExpression
: 'DirectCast' OpenParenthesis Expression Comma TypeName CloseParenthesis
| 'TryCast' OpenParenthesis Expression Comma TypeName CloseParenthesis
| 'CType' OpenParenthesis Expression Comma TypeName CloseParenthesis
| CastTarget OpenParenthesis Expression CloseParenthesis
;
CastTarget
: 'CBool' | 'CByte' | 'CChar' | 'CDate' | 'CDec' | 'CDbl' | 'CInt'
| 'CLng' | 'CObj' | 'CSByte' | 'CShort' | 'CSng' | 'CStr' | 'CUInt'
| 'CULng' | 'CUShort'
;
DirectCast dan TryCast memiliki perilaku khusus. Karena itu, mereka hanya mendukung konversi asli. Selain itu, jenis target dalam TryCast ekspresi tidak boleh berupa jenis nilai. Operator konversi yang ditentukan pengguna tidak dipertimbangkan saat DirectCast atau TryCast digunakan. (Catatan. Set konversi yang DirectCast dan TryCast dukungan dibatasi karena menerapkan konversi "CLR asli". Tujuannya DirectCast adalah untuk memberikan fungsionalitas instruksi "unbox", sementara tujuannya TryCast adalah untuk memberikan fungsionalitas instruksi "isinst". Karena mereka memetakan ke instruksi CLR, konversi pendukung yang tidak didukung langsung oleh CLR akan mengalahkan tujuan yang dimaksudkan.)
DirectCast mengonversi ekspresi yang ditik sebagai Object berbeda dari CType. Saat mengonversi ekspresi jenis Object yang jenis run-time-nya adalah jenis nilai primitif, DirectCast melemparkan System.InvalidCastException pengecualian jika jenis yang ditentukan tidak sama dengan jenis run-time ekspresi atau System.NullReferenceException jika ekspresi mengevaluasi ke Nothing. (Catatan. Seperti disebutkan di atas, DirectCast peta langsung ke instruksi CLR "unbox" ketika jenis ekspresi adalah Object. Sebaliknya, CType berubah menjadi panggilan ke pembantu runtime untuk melakukan konversi sehingga konversi antara jenis primitif dapat didukung. Dalam kasus ketika Object ekspresi sedang dikonversi ke jenis nilai primitif dan jenis instans aktual cocok dengan jenis target, DirectCast akan jauh lebih cepat daripada CType.)
TryCast mengonversi ekspresi tetapi tidak melemparkan pengecualian jika ekspresi tidak dapat dikonversi ke jenis target. Sebaliknya, TryCast akan mengakibatkan jika ekspresi tidak dapat dikonversi Nothing pada runtime. (Catatan. Seperti disebutkan di atas, TryCast peta langsung ke instruksi CLR "isinst". Dengan menggabungkan pemeriksaan jenis dan konversi menjadi satu operasi, TryCast bisa lebih murah daripada melakukan TypeOf ... Is dan kemudian CType.)
Contohnya:
Interface ITest
Sub Test()
End Interface
Module Test
Sub Convert(o As Object)
Dim i As ITest = TryCast(o, ITest)
If i IsNot Nothing Then
i.Test()
End If
End Sub
End Module
Jika tidak ada konversi dari jenis ekspresi ke jenis yang ditentukan, kesalahan waktu kompilasi terjadi. Jika tidak, ekspresi diklasifikasikan sebagai nilai dan hasilnya adalah nilai yang dihasilkan oleh konversi.
Ekspresi Operator
Ada dua jenis operator.
Operator unary mengambil satu operand dan menggunakan notasi awalan (misalnya, -x).
Operator biner mengambil dua operand dan menggunakan notasi infiks (misalnya, x + y). Dengan pengecualian operator relasional, yang selalu menghasilkan Boolean, operator yang ditentukan untuk jenis tertentu menghasilkan jenis tersebut. Operand ke operator harus selalu diklasifikasikan sebagai nilai; hasil ekspresi operator diklasifikasikan sebagai nilai.
OperatorExpression
: ArithmeticOperatorExpression
| RelationalOperatorExpression
| LikeOperatorExpression
| ConcatenationOperatorExpression
| ShortCircuitLogicalOperatorExpression
| LogicalOperatorExpression
| ShiftOperatorExpression
| AwaitOperatorExpression
;
Prioritas Operator dan Asosiativitas
Saat ekspresi berisi beberapa operator biner, prioritas operator mengontrol urutan operator biner individu dievaluasi. Misalnya, ekspresi x + y * z dievaluasi sebagai x + (y * z) karena * operator memiliki prioritas yang lebih tinggi daripada + operator. Tabel berikut ini mencantumkan operator biner dalam urutan menurutan prioritas:
| Kategori | Operator |
|---|---|
| Utama | Semua ekspresi non-operator |
| Menunggu | Await |
| Pemangkatan | ^ |
| Negasi unary |
+, - |
| bersifat perkalian |
*, / |
| Pembagian bilangan bulat | \ |
| Modulus | Mod |
| Aditif |
+, - |
| Penggabungan | & |
| Pergeseran |
<<, >> |
| Relasional |
=, , <<>, >, <=, >=, Like, , Is,IsNot |
| Bukan Logis | Not |
| DAN Logika |
And, AndAlso |
| ATAU Logika |
Or, OrElse |
| XOR Logika | Xor |
Ketika ekspresi berisi dua operator dengan prioritas yang sama, asositivitas operator mengontrol urutan operasi dilakukan. Semua operator biner bersifat asosiatif kiri, yang berarti bahwa operasi dilakukan dari kiri ke kanan. Prioritas dan asokiativitas dapat dikontrol menggunakan ekspresi kurung.
Operand Objek
Selain jenis reguler yang didukung oleh setiap operator, semua operator mendukung operand jenis Object. Operator yang diterapkan ke Object operand ditangani mirip dengan panggilan metode yang dilakukan pada Object nilai: panggilan metode yang terlambat terikat mungkin dipilih, dalam hal ini jenis run-time operand, bukan jenis waktu kompilasi, menentukan validitas dan jenis operasi. Jika semantik ketat ditentukan oleh lingkungan kompilasi atau oleh Option Strict, operator apa pun dengan operand jenis Object menyebabkan kesalahan waktu kompilasi, kecuali untuk TypeOf...Isoperator , Is dan IsNot .
Ketika resolusi operator menentukan bahwa operasi harus dilakukan terlambat terikat, hasil operasi adalah hasil dari menerapkan operator ke jenis operand jika jenis run-time operand adalah jenis yang didukung oleh operator. Nilai Nothing diperlakukan sebagai nilai default dari jenis operand lain dalam ekspresi operator biner. Dalam ekspresi operator unary, atau jika kedua operand berada Nothing dalam ekspresi operator biner, jenis operasi adalah Integer atau satu-satunya jenis hasil operator, jika operator tidak menghasilkan Integer. Hasil operasi selalu dilemparkan kembali ke Object. Jika jenis operand tidak memiliki operator yang System.InvalidCastException valid, pengecualian akan dilemparkan. Konversi pada waktu proses dilakukan tanpa memperhatikan apakah itu implisit atau eksplisit.
Jika hasil operasi biner numerik akan menghasilkan pengecualian luapan (terlepas dari apakah pemeriksaan luapan bilangan bulat aktif atau nonaktif), maka jenis hasil dipromosikan ke jenis numerik yang lebih luas berikutnya, jika memungkinkan. Misalnya, pertimbangkan kode berikut:
Module Test
Sub Main()
Dim o As Object = CObj(CByte(2)) * CObj(CByte(255))
Console.WriteLine(o.GetType().ToString() & " = " & o)
End Sub
End Module
Ini mencetak hasil berikut:
System.Int16 = 512
Jika tidak ada jenis numerik yang lebih luas yang tersedia untuk menahan angka, System.OverflowException pengecualian akan dilemparkan.
Resolusi Operator
Mengingat jenis operator dan sekumpulan operand, resolusi operator menentukan operator mana yang akan digunakan untuk operand. Saat menyelesaikan operator, operator yang ditentukan pengguna akan dipertimbangkan terlebih dahulu, menggunakan langkah-langkah berikut:
Pertama, semua operator kandidat dikumpulkan. Operator kandidat adalah semua operator yang ditentukan pengguna dari jenis operator tertentu dalam jenis sumber dan semua operator yang ditentukan pengguna dari jenis target tertentu. Jika jenis sumber dan jenis tujuan terkait, operator umum hanya dipertimbangkan sekali.
Kemudian, resolusi kelebihan beban diterapkan ke operator dan operand untuk memilih operator yang paling spesifik. Dalam kasus operator biner, ini dapat mengakibatkan panggilan terlambat terikat.
Saat mengumpulkan operator kandidat untuk jenis T?, operator jenis T digunakan sebagai gantinya.
TSalah satu operator yang ditentukan pengguna yang hanya melibatkan jenis nilai yang tidak dapat diubah ke null juga diangkat. Operator yang diangkat menggunakan versi nullable dari jenis nilai apa pun, dengan pengecualian jenis IsTrue pengembalian dan IsFalse (yang harus Boolean). Operator yang diangkat dievaluasi dengan mengonversi operand ke versi yang tidak dapat diubah ke null, lalu mengevaluasi operator yang ditentukan pengguna lalu mengonversi jenis hasil ke versi nullable-nya. Jika operand ether adalah Nothing, hasil ekspresi adalah nilai yang ditik Nothing sebagai versi nullable dari jenis hasil. Contohnya:
Structure T
...
End Structure
Structure S
Public Shared Operator +(ByVal op1 As S, ByVal op2 As T) As T
...
End Operator
End Structure
Module Test
Sub Main()
Dim x As S?
Dim y, z As T?
' Valid, as S + T = T is lifted to S? + T? = T?
z = x + y
End Sub
End Module
Jika operator adalah operator biner dan salah satu operand adalah jenis referensi, operator juga diangkat, tetapi pengikatan apa pun ke operator menghasilkan kesalahan. Contohnya:
Structure S1
Public F1 As Integer
Public Shared Operator +(left As S1, right As String) As S1
...
End Operator
End Structure
Module Test
Sub Main()
Dim a? As S1
Dim s As String
' Error: '+' is not defined for S1? and String
a = a + s
End Sub
End Module
Nota. Aturan ini ada karena telah ada pertimbangan apakah kami ingin menambahkan jenis referensi penyebaran null dalam versi mendatang, dalam hal ini perilaku dalam kasus operator biner antara kedua jenis akan berubah.
Seperti halnya konversi, operator yang ditentukan pengguna selalu lebih disukai daripada operator yang diangkat.
Saat menyelesaikan operator yang kelebihan beban, mungkin ada perbedaan antara kelas yang ditentukan dalam Visual Basic dan yang ditentukan dalam bahasa lain:
Dalam bahasa lain,
Not,And, danOrdapat kelebihan beban baik sebagai operator logis maupun operator bitwise. Setelah mengimpor dari rakitan eksternal, salah satu formulir diterima sebagai kelebihan beban yang valid untuk operator ini. Namun, untuk jenis yang mendefinisikan operator logis dan bitwise, hanya implementasi bitwise yang akan dipertimbangkan.Dalam bahasa lain,
>>dan<<mungkin kelebihan beban baik sebagai operator yang ditandatangani maupun operator yang tidak ditandatangani. Setelah mengimpor dari rakitan eksternal, salah satu formulir diterima sebagai kelebihan beban yang valid. Namun, untuk jenis yang menentukan operator yang ditandatangani dan tidak ditandatangani, hanya implementasi yang ditandatangani yang akan dipertimbangkan.Jika tidak ada operator yang ditentukan pengguna yang paling spesifik untuk operand, maka operator intrinsik akan dipertimbangkan. Jika tidak ada operator intrinsik yang didefinisikan untuk operand dan salah satu operand memiliki tipe Objek maka operator akan diselesaikan terlambat terikat; jika tidak, hasil kesalahan waktu kompilasi.
Dalam versi Visual Basic sebelumnya, jika ada tepat satu operan jenis Objek, dan tidak ada operator yang ditentukan pengguna yang berlaku, dan tidak ada operator intrinsik yang berlaku, maka itu adalah kesalahan. Pada Visual Basic 11, sekarang diselesaikan terlambat terikat. Contohnya:
Module Module1
Sub Main()
Dim p As Object = Nothing
Dim U As New Uri("http://www.microsoft.com")
Dim j = U * p ' is now resolved late-bound
End Sub
End Module
Jenis T yang memiliki operator intrinsik juga menentukan operator yang sama untuk T?. Hasil operator pada T? akan sama seperti untuk T, kecuali bahwa jika salah satu operand adalah Nothing, hasil operator akan menjadi Nothing (yaitu nilai null disebarkan). Untuk tujuan menyelesaikan jenis operasi, ? dihapus dari setiap operand yang memilikinya, jenis operasi ditentukan, dan ? ditambahkan ke jenis operasi jika salah satu operand adalah jenis nilai nullable. Contohnya:
Dim v1? As Integer = 10
Dim v2 As Long = 20
' Type of operation will be Long?
Console.WriteLine(v1 + v2)
Setiap operator mencantumkan jenis intrinsik yang didefinisikannya dan jenis operasi yang dilakukan mengingat jenis operand. Hasil dari jenis operasi intrinsik mengikuti aturan umum ini:
Jika semua operand memiliki jenis yang sama, dan operator didefinisikan untuk jenis tersebut, maka tidak ada konversi yang terjadi dan operator untuk jenis tersebut digunakan.
Setiap operan yang jenisnya tidak ditentukan untuk operator dikonversi menggunakan langkah-langkah berikut dan operator diselesaikan terhadap jenis baru:
Operand dikonversi ke jenis terluas berikutnya yang didefinisikan untuk operator dan operand dan yang secara implisit dapat dikonversi.
Jika tidak ada jenis seperti itu, maka operand dikonversi ke jenis tersempit berikutnya yang ditentukan untuk operator dan operand dan yang secara implisit dapat dikonversi.
Jika tidak ada jenis seperti itu atau konversi tidak dapat terjadi, kesalahan waktu kompilasi terjadi.
Jika tidak, operand dikonversi ke lebih luas dari jenis operand dan operator untuk jenis tersebut digunakan. Jika jenis operand yang lebih sempit tidak dapat dikonversi secara implisit ke jenis operator yang lebih luas, kesalahan waktu kompilasi terjadi.
Namun, terlepas dari aturan umum ini, ada sejumlah kasus khusus yang dipanggil dalam tabel hasil operator.
Nota. Untuk alasan pemformatan, tabel jenis operator singkatan nama yang telah ditentukan sebelumnya ke dua karakter pertamanya. Jadi "Oleh" adalah Byte, "UI" adalah UInteger, "St" adalah String, dll. "Err" berarti bahwa tidak ada operasi yang ditentukan untuk jenis operand yang diberikan.
Operator Aritmatika
Operator *, , \/, ^Mod, +, dan - adalah operator aritmatika.
ArithmeticOperatorExpression
: UnaryPlusExpression
| UnaryMinusExpression
| AdditionOperatorExpression
| SubtractionOperatorExpression
| MultiplicationOperatorExpression
| DivisionOperatorExpression
| ModuloOperatorExpression
| ExponentOperatorExpression
;
Operasi aritmatika floating-point dapat dilakukan dengan presisi yang lebih tinggi daripada jenis hasil operasi. Misalnya, beberapa arsitektur perangkat keras mendukung jenis titik mengambang "diperluas" atau "ganda panjang" dengan rentang dan presisi yang lebih besar daripada jenisnya Double , dan secara implisit melakukan semua operasi floating-point menggunakan jenis presisi yang lebih tinggi ini. Arsitektur perangkat keras dapat dibuat untuk melakukan operasi floating-point dengan presisi yang lebih sedikit hanya dengan biaya performa yang berlebihan; daripada memerlukan implementasi untuk kehilangan performa dan presisi, Visual Basic memungkinkan jenis presisi yang lebih tinggi untuk digunakan untuk semua operasi floating-point. Selain memberikan hasil yang lebih tepat, ini jarang memiliki efek terukur. Namun, dalam ekspresi formulir x * y / z, di mana perkalian menghasilkan hasil yang berada di luar Double rentang, tetapi pembagian berikutnya membawa hasil sementara kembali ke dalam Double rentang, fakta bahwa ekspresi dievaluasi dalam format rentang yang lebih tinggi dapat menyebabkan hasil terbatas diproduksi alih-alih tak terbatas.
Unary Plus Operator
UnaryPlusExpression
: '+' Expression
;
Operator unary plus didefinisikan untuk Bytejenis , , SByte, UShortShort, UInteger, ULongInteger, Long, Single, Doubledan Decimal .
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sh | SB | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob |
Unary Minus Operator
UnaryMinusExpression
: '-' Expression
;
Operator minus unary didefinisikan untuk jenis berikut:
SByte, Short, Integer, dan Long. Hasilnya dihitung dengan mengurangi operan dari nol. Jika pemeriksaan luapan bilangan bulat aktif dan nilai operand adalah negatif SBytemaksimum , , Short, Integeratau Long, System.OverflowException pengecualian dilemparkan. Jika tidak, jika nilai operand adalah negatif SBytemaksimum , , Short, Integeratau Long, hasilnya adalah nilai yang sama, dan luapan tidak dilaporkan.
Single dan Double. Hasilnya adalah nilai operand dengan tanda terbalik, termasuk nilai 0 dan Infinity. Jika operan adalah NaN, hasilnya juga NaN.
Decimal. Hasilnya dihitung dengan mengurangi operan dari nol.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob |
Operator Penambahan
Operator penambahan menghitung jumlah dua operand.
AdditionOperatorExpression
: Expression '+' LineTerminator? Expression
;
Operator penambahan didefinisikan untuk jenis berikut:
Byte, ,SByte,UShortShort,UInteger,Integer, ,ULong, danLong. Jika pemeriksaan luapan bilangan bulat aktif dan jumlahnya berada di luar rentang jenis hasil,System.OverflowExceptionpengecualian akan dilemparkan. Jika tidak, luapan tidak dilaporkan, dan bit urutan tinggi yang signifikan dari hasilnya dibuang.SingledanDouble. Jumlah dihitung sesuai dengan aturan aritmatika IEEE 754.Decimal. Jika nilai yang dihasilkan terlalu besar untuk diwakili dalam format desimal,System.OverflowExceptionpengecualian akan dilemparkan. Jika nilai hasil terlalu kecil untuk diwakili dalam format desimal, hasilnya adalah 0.String. KeduaStringoperan digabungkan bersama-sama.Date. Jenis menentukanSystem.DateTimeoperator penambahan yang kelebihan beban. KarenaSystem.DateTimesetara dengan jenis intrinsikDate, operator ini juga tersedia pada jenisnyaDate.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | St | Err | St | Ob | ||||||||||||
| Ch | St | St | Ob | |||||||||||||
| St | St | Ob | ||||||||||||||
| Ob | Ob |
Operator Pengurangan
Operator pengurangan mengurangi operand kedua dari operand pertama.
SubtractionOperatorExpression
: Expression '-' LineTerminator? Expression
;
Operator pengurangan ditentukan untuk jenis berikut:
Byte, ,SByte,UShortShort,UInteger,Integer, ,ULong, danLong. Jika pemeriksaan luapan bilangan bulat aktif dan perbedaannya berada di luar rentang jenis hasil,System.OverflowExceptionpengecualian akan dilemparkan. Jika tidak, luapan tidak dilaporkan, dan bit urutan tinggi yang signifikan dari hasilnya dibuang.SingledanDouble. Perbedaannya dihitung sesuai dengan aturan aritmatika IEEE 754.Decimal. Jika nilai yang dihasilkan terlalu besar untuk diwakili dalam format desimal,System.OverflowExceptionpengecualian akan dilemparkan. Jika nilai hasil terlalu kecil untuk diwakili dalam format desimal, hasilnya adalah 0.Date. Jenis mendefinisikanSystem.DateTimeoperator pengurangan yang kelebihan beban. KarenaSystem.DateTimesetara dengan jenis intrinsikDate, operator ini juga tersedia pada jenisnyaDate.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lakukan | Ob | ||||||||||||||
| Ob | Ob |
Operator Perkalian
Operator perkalian menghitung produk dari dua operand.
MultiplicationOperatorExpression
: Expression '*' LineTerminator? Expression
;
Operator perkalian didefinisikan untuk jenis berikut:
Byte, ,SByte,UShortShort,UInteger,Integer, ,ULong, danLong. Jika pemeriksaan luapan bilangan bulat aktif dan produk berada di luar rentang jenis hasil,System.OverflowExceptionpengecualian akan dilemparkan. Jika tidak, luapan tidak dilaporkan, dan bit urutan tinggi yang signifikan dari hasilnya dibuang.SingledanDouble. Produk ini dihitung sesuai dengan aturan aritmatika IEEE 754.Decimal. Jika nilai yang dihasilkan terlalu besar untuk diwakili dalam format desimal,System.OverflowExceptionpengecualian akan dilemparkan. Jika nilai hasil terlalu kecil untuk diwakili dalam format desimal, hasilnya adalah 0.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lakukan | Ob | ||||||||||||||
| Ob | Ob |
Operator Divisi
Operator divisi menghitung kuota dua operand. Ada dua operator divisi: operator divisi reguler (floating-point) dan operator divisi bilangan bulat.
DivisionOperatorExpression
: FPDivisionOperatorExpression
| IntegerDivisionOperatorExpression
;
FPDivisionOperatorExpression
: Expression '/' LineTerminator? Expression
;
IntegerDivisionOperatorExpression
: Expression '\\' LineTerminator? Expression
;
Operator pembagian reguler didefinisikan untuk jenis berikut:
SingledanDouble. Kuota dihitung sesuai dengan aturan aritmatika IEEE 754.Decimal. Jika nilai operand kanan adalah nol,System.DivideByZeroExceptionpengecualian akan dilemparkan. Jika nilai yang dihasilkan terlalu besar untuk diwakili dalam format desimal,System.OverflowExceptionpengecualian akan dilemparkan. Jika nilai hasil terlalu kecil untuk direpresentasikan dalam format desimal, hasilnya adalah nol. Skala hasil, sebelum pembulatan apa pun, adalah skala terdekat dengan skala pilihan yang akan mempertahankan hasil yang sama dengan hasil yang tepat. Skala yang disukai adalah skala operand pertama lebih sedikit skala operand kedua.
Menurut aturan resolusi operator normal, pembagian reguler murni antara operan jenis seperti Byte, , ShortInteger, dan Long akan menyebabkan kedua operan dikonversi ke jenis Decimal. Namun, ketika melakukan resolusi operator pada operator divisi ketika tidak ada jenis yang Decimal, Double dianggap lebih sempit daripada Decimal. Konvensi ini diikuti karena Double pembagian lebih efisien daripada Decimal pembagian.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob |
| SB | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Lakukan | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Lakukan | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lakukan | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | Lakukan | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lakukan | Ob | ||||||||||||||
| Ob | Ob |
Operator pembagian bilangan bulat didefinisikan untuk Byte, , SByte, ShortUShort, UInteger, Integer, ULong, dan Long. Jika nilai operand kanan adalah nol, System.DivideByZeroException pengecualian akan dilemparkan. Pembagian membulatkan hasil menuju nol, dan nilai absolut hasil adalah bilangan bulat terbesar yang mungkin kurang dari nilai absolut dari kuota dua operan. Hasilnya adalah nol atau positif ketika kedua operand memiliki tanda yang sama, dan nol atau negatif ketika kedua operand memiliki tanda-tanda berlawanan. Jika operand kiri adalah negatif SBytemaksimum , , Short, Integeratau Long, dan operand kanan adalah -1, luapan terjadi; jika pemeriksaan luapan bilangan bulat aktif, System.OverflowException pengecualian akan dilemparkan. Jika tidak, luapan tidak dilaporkan dan hasilnya adalah nilai operand kiri.
Nota. Karena dua operan untuk jenis yang tidak ditandatangani akan selalu nol atau positif, hasilnya selalu nol atau positif. Karena hasil ekspresi akan selalu kurang dari atau sama dengan yang terbesar dari dua operan, tidak dimungkinkan untuk terjadinya luapan. Dengan demikian pemeriksaan luapan bilangan bulat tidak dilakukan untuk pembagian bilangan bulat dengan dua bilangan bulat yang tidak ditandatangani. Hasilnya adalah jenis sebagai dari operand kiri.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||
| Di | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||||
| Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||||
| UL | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||||||
| De | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||||||
| Si | Lo | Lo | Err | Err | Lo | Ob | ||||||||||
| Lakukan | Lo | Err | Err | Lo | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lo | Ob | ||||||||||||||
| Ob | Ob |
Mod Operator
Operator Mod (modulo) menghitung sisa pembagian antara dua operan.
ModuloOperatorExpression
: Expression 'Mod' LineTerminator? Expression
;
Operator Mod didefinisikan untuk jenis berikut:
Byte, ,SByte,ShortUShort,UInteger,Integer, ,ULongdanLong. Hasilx Mod yadalah nilai yang dihasilkan olehx - (x \ y) * y. Jikaynol,System.DivideByZeroExceptionpengecualian akan dilemparkan. Operator modulo tidak pernah menyebabkan luapan.SingledanDouble. Sisanya dihitung sesuai dengan aturan aritmatika IEEE 754.Decimal. Jika nilai operand kanan adalah nol,System.DivideByZeroExceptionpengecualian akan dilemparkan. Jika nilai yang dihasilkan terlalu besar untuk diwakili dalam format desimal,System.OverflowExceptionpengecualian akan dilemparkan. Jika nilai hasil terlalu kecil untuk direpresentasikan dalam format desimal, hasilnya adalah nol.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Sh | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lakukan | Ob | ||||||||||||||
| Ob | Ob |
Operator Eksponensial
Operator eksponensial menghitung operand pertama yang dinaikkan ke daya operand kedua.
ExponentOperatorExpression
: Expression '^' LineTerminator? Expression
;
Operator eksponensial didefinisikan untuk jenis Double. Nilai dihitung sesuai dengan aturan aritmatika IEEE 754.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob |
| SB | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lakukan | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | Lakukan | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | Lakukan | Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Lakukan | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lakukan | Ob | ||||||||||||||
| Ob | Ob |
Operator Relasional
Operator relasional membandingkan nilai satu sama lain. Operator perbandingan adalah =, , <>, <, >, <=, dan >=.
RelationalOperatorExpression
: Expression '=' LineTerminator? Expression
| Expression '<' '>' LineTerminator? Expression
| Expression '<' LineTerminator? Expression
| Expression '>' LineTerminator? Expression
| Expression '<' '=' LineTerminator? Expression
| Expression '>' '=' LineTerminator? Expression
;
Semua operator relasional menghasilkan Boolean nilai.
Operator relasional memiliki arti umum berikut:
Operator
=menguji apakah kedua operand sama.Operator
<>menguji apakah kedua operand tidak sama.Operator
<menguji apakah operand pertama kurang dari operand kedua.Operator
>menguji apakah operand pertama lebih besar dari operand kedua.Operator
<=menguji apakah operand pertama kurang dari atau sama dengan operand kedua.Operator
>=menguji apakah operand pertama lebih besar dari atau sama dengan operand kedua.
Operator relasional didefinisikan untuk jenis berikut:
Boolean. Operator membandingkan nilai kebenaran dari dua operand.Truedianggap kurang dariFalse, yang cocok dengan nilai numeriknya.Byte, ,SByte,UShortShort,UInteger,Integer, ,ULong, danLong. Operator membandingkan nilai numerik dari dua operand integral.SingledanDouble. Operator membandingkan operand sesuai dengan aturan standar IEEE 754.Decimal. Operator membandingkan nilai numerik dari dua operand desimal.Date. Operator mengembalikan hasil membandingkan dua nilai tanggal/waktu.Char. Operator mengembalikan hasil membandingkan dua nilai Unicode.String. Operator mengembalikan hasil membandingkan dua nilai menggunakan perbandingan biner atau perbandingan teks. Perbandingan yang digunakan ditentukan oleh lingkungan kompilasi danOption Comparepernyataan. Perbandingan biner menentukan apakah nilai Unicode numerik dari setiap karakter di setiap string sama. Perbandingan teks melakukan perbandingan teks Unicode berdasarkan budaya saat ini yang digunakan pada .NET Framework. Saat melakukan perbandingan string, nilai null setara dengan string literal"".
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Bo | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Bo | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||
| Di | Di dalam | Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||
| Lo | Lo | De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||
| UL | UL | De | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||
| De | De | Si | Lakukan | Err | Err | Lakukan | Ob | |||||||||
| Si | Si | Lakukan | Err | Err | Lakukan | Ob | ||||||||||
| Lakukan | Lakukan | Err | Err | Lakukan | Ob | |||||||||||
| Da | Da | Err | Da | Ob | ||||||||||||
| Ch | Ch | St | Ob | |||||||||||||
| St | St | Ob | ||||||||||||||
| Ob | Ob |
Like Operator
Operator Like menentukan apakah string cocok dengan pola tertentu.
LikeOperatorExpression
: Expression 'Like' LineTerminator? Expression
;
Operator Like didefinisikan untuk jenis tersebut String . Operan pertama adalah string yang dicocokkan, dan operand kedua adalah pola yang cocok dengan. Pola ini terdiri dari karakter Unicode. Urutan karakter berikut memiliki arti khusus:
Karakter
?cocok dengan karakter tunggal apa pun.Karakter
*cocok dengan nol karakter atau lebih.Karakter
#cocok dengan satu digit (0-9).Daftar karakter yang dikelilingi oleh tanda kurung siku (
[ab...]) cocok dengan satu karakter dalam daftar.Daftar karakter yang dikelilingi oleh tanda kurung siku dan diawali oleh tanda seru (
[!ab...]) cocok dengan satu karakter yang tidak ada dalam daftar karakter.Dua karakter dalam daftar karakter yang dipisahkan oleh tanda hubung (
-) menentukan rentang karakter Unicode yang dimulai dengan karakter pertama dan diakhir dengan karakter kedua. Jika karakter kedua tidak nanti dalam urutan pengurutan daripada karakter pertama, pengecualian run-time terjadi. Tanda hubung yang muncul di awal atau akhir daftar karakter menentukan dirinya sendiri.
Untuk mencocokkan karakter khusus kurung kiri ([), tanda tanya (?), tanda angka (#), dan tanda bintang (*), tanda kurung harus mengapitnya. Kurung siku kanan (]) tidak dapat digunakan dalam grup untuk mencocokkan dirinya sendiri, tetapi dapat digunakan di luar grup sebagai karakter individual. Urutan [] karakter dianggap sebagai string literal "".
Perhatikan bahwa perbandingan karakter dan pengurutan untuk daftar karakter bergantung pada jenis perbandingan yang digunakan. Jika perbandingan biner digunakan, perbandingan karakter dan pengurutan didasarkan pada nilai Unicode numerik. Jika perbandingan teks digunakan, perbandingan karakter dan pengurutan didasarkan pada lokal saat ini yang digunakan pada .NET Framework.
Dalam beberapa bahasa, karakter khusus dalam alfabet mewakili dua karakter terpisah dan sebaliknya. Misalnya, beberapa bahasa menggunakan karakter æ untuk mewakili karakter a dan e ketika muncul bersama-sama, sementara karakter ^ dan O dapat digunakan untuk mewakili karakter Ô. Saat menggunakan perbandingan teks, Like operator mengenali kesetaraan budaya tersebut. Dalam hal ini, terjadinya karakter khusus tunggal dalam pola atau string cocok dengan urutan dua karakter yang setara di string lainnya. Demikian pula, satu karakter khusus dalam pola yang diapit dalam tanda kurung siku (dengan sendirinya, dalam daftar, atau dalam rentang) cocok dengan urutan dua karakter yang setara dalam string dan sebaliknya.
Like Dalam ekspresi di mana kedua operand adalah Nothing atau satu operand memiliki konversi intrinsik ke String dan operand lainnya adalah Nothing, Nothing diperlakukan seolah-olah itu adalah string kosong harfiah "".
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | St | St | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob |
| SB | St | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob | |
| Oleh | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob | ||
| Sh | St | St | St | St | St | St | St | St | St | St | St | St | Ob | |||
| US | St | St | St | St | St | St | St | St | St | St | St | Ob | ||||
| Di | St | St | St | St | St | St | St | St | St | St | Ob | |||||
| UI | St | St | St | St | St | St | St | St | St | Ob | ||||||
| Lo | St | St | St | St | St | St | St | St | Ob | |||||||
| UL | St | St | St | St | St | St | St | Ob | ||||||||
| De | St | St | St | St | St | St | Ob | |||||||||
| Si | St | St | St | St | St | Ob | ||||||||||
| Lakukan | St | St | St | St | Ob | |||||||||||
| Da | St | St | St | Ob | ||||||||||||
| Ch | St | St | Ob | |||||||||||||
| St | St | Ob | ||||||||||||||
| Ob | Ob |
Operator Penggalian
ConcatenationOperatorExpression
: Expression '&' LineTerminator? Expression
;
Operator perangkaian didefinisikan untuk semua jenis intrinsik, termasuk versi nullable dari jenis nilai intrinsik. Ini juga didefinisikan untuk perangkaian antara jenis yang disebutkan di atas dan System.DBNull, yang diperlakukan sebagai Nothing string. Operator perangkaian mengonversi semua operannya menjadi String; dalam ekspresi, semua konversi String dianggap melebar, terlepas dari apakah semantik ketat digunakan. Nilai System.DBNull dikonversi ke literal Nothing yang dititik sebagai String. Jenis nilai nullable yang nilainya Nothing juga dikonversi ke literal Nothing yang dititik sebagai String, daripada melemparkan kesalahan run-time.
Operasi penggambungan menghasilkan string yang merupakan perangkaian dua operan secara berurutan dari kiri ke kanan. Nilai Nothing diperlakukan seolah-olah itu adalah string kosong harfiah "".
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | St | St | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob |
| SB | St | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob | |
| Oleh | St | St | St | St | St | St | St | St | St | St | St | St | St | Ob | ||
| Sh | St | St | St | St | St | St | St | St | St | St | St | St | Ob | |||
| US | St | St | St | St | St | St | St | St | St | St | St | Ob | ||||
| Di | St | St | St | St | St | St | St | St | St | St | Ob | |||||
| UI | St | St | St | St | St | St | St | St | St | Ob | ||||||
| Lo | St | St | St | St | St | St | St | St | Ob | |||||||
| UL | St | St | St | St | St | St | St | Ob | ||||||||
| De | St | St | St | St | St | St | Ob | |||||||||
| Si | St | St | St | St | St | Ob | ||||||||||
| Lakukan | St | St | St | St | Ob | |||||||||||
| Da | St | St | St | Ob | ||||||||||||
| Ch | St | St | Ob | |||||||||||||
| St | St | Ob | ||||||||||||||
| Ob | Ob |
Operator Logis
Operator And, Not, Or, dan Xor disebut operator logis.
LogicalOperatorExpression
: 'Not' Expression
| Expression 'And' LineTerminator? Expression
| Expression 'Or' LineTerminator? Expression
| Expression 'Xor' LineTerminator? Expression
;
Operator logis dievaluasi sebagai berikut:
Untuk jenis:
BooleanOperasi logis
Anddilakukan pada dua operannya.Operasi logis
Notdilakukan pada operand-nya.Operasi logis
Ordilakukan pada dua operannya.Operasi eksklusif
Orlogis dilakukan pada dua operannya.
Untuk
Byte, ,SByte,ShortUShort,UInteger,Integer,ULong, ,Long, dan semua jenis enumerasi, operasi yang ditentukan dilakukan pada setiap bit representasi biner dari dua operand:And: Bit hasil adalah 1 jika kedua bit adalah 1; jika tidak, bit hasilnya adalah 0.Not: Bit hasil adalah 1 jika bit adalah 0; jika tidak, bit hasilnya adalah 1.Or: Bit hasil adalah 1 jika salah satu bit adalah 1; jika tidak, bit hasilnya adalah 0.Xor: Bit hasil adalah 1 jika salah satu bit adalah 1 tetapi bukan kedua bit; jika tidak, bit hasilnya adalah 0 (yaitu, 1Xor0 = 1, 1Xor1 = 0).
Ketika operator
Andlogis danOrdiangkat untuk jenisBoolean?, operator tersebut diperluas untuk mencakup logika Boolean tiga nilai seperti:Andmengevaluasi ke true jika kedua operan tersebut benar; false jika salah satu operan salah;NothingSebaliknya.Ormengevaluasi ke true jika salah satu operand benar; false adalah kedua operan adalah false;NothingSebaliknya.
Contohnya:
Module Test
Sub Main()
Dim x?, y? As Boolean
x = Nothing
y = True
If x Or y Then
' Will execute
End If
End Sub
End Module
Nota. Idealnya, operator And logis dan Or akan diangkat menggunakan logika tiga nilai untuk jenis apa pun yang dapat digunakan dalam ekspresi Boolean (yaitu jenis yang mengimplementasikan IsTrue dan IsFalse), dengan cara yang sama seperti itu AndAlso dan OrElse sirkuit pendek di semua jenis yang dapat digunakan dalam ekspresi Boolean. Sayangnya, pengangkatan tiga nilai hanya diterapkan ke Boolean?, sehingga jenis yang ditentukan pengguna yang menginginkan logika tiga nilai harus melakukannya secara manual dengan mendefinisikan And dan Or operator untuk versi nullable mereka.
Tidak ada luapan yang dimungkinkan dari operasi ini. Operator jenis enumerasi melakukan operasi bitwise pada jenis yang mendasar dari jenis enumerasi, tetapi nilai yang dikembalikan adalah jenis enumerasi.
Bukan Tipe Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | SB | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob |
Dan, atau, Jenis operasi Xor:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Bo | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Bo | Ob |
| SB | SB | Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |
| Oleh | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||
| Sh | Sh | Di dalam | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||
| US | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||
| Di | Di dalam | Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||
| UI | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||||
| Lo | Lo | Lo | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||||
| UL | UL | Lo | Lo | Lo | Err | Err | Lo | Ob | ||||||||
| De | Lo | Lo | Lo | Err | Err | Lo | Ob | |||||||||
| Si | Lo | Lo | Err | Err | Lo | Ob | ||||||||||
| Lakukan | Lo | Err | Err | Lo | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Lo | Ob | ||||||||||||||
| Ob | Ob |
Operator Logis Sirkuit Pendek
Operator AndAlso dan OrElse adalah versi sirkuit pendek dari And operator logis dan Or .
ShortCircuitLogicalOperatorExpression
: Expression 'AndAlso' LineTerminator? Expression
| Expression 'OrElse' LineTerminator? Expression
;
Karena perilaku sirkuit pendek mereka, operan kedua tidak dievaluasi pada waktu proses jika hasil operator diketahui setelah mengevaluasi operand pertama.
Operator logis sirkuit pendek dievaluasi sebagai berikut:
Jika operand pertama dalam
AndAlsooperasi mengevaluasi keFalseatau mengembalikan True dari operatornyaIsFalse, ekspresi mengembalikan operand pertamanya. Jika tidak, operan kedua dievaluasi dan operasi logisAnddilakukan pada dua hasil.Jika operand pertama dalam
OrElseoperasi mengevaluasi keTrueatau mengembalikan True dari operatornyaIsTrue, ekspresi mengembalikan operand pertamanya. Jika tidak, operand kedua dievaluasi dan operasi logisOrdilakukan pada dua hasilnya.
Operator AndAlso dan OrElse didefinisikan untuk jenis Boolean, atau untuk jenis T apa pun yang membebani operator berikut:
Public Shared Operator IsTrue(op As T) As Boolean
Public Shared Operator IsFalse(op As T) As Boolean
serta kelebihan beban yang sesuai And atau Or operator:
Public Shared Operator And(op1 As T, op2 As T) As T
Public Shared Operator Or(op1 As T, op2 As T) As T
Saat mengevaluasi AndAlso operator atau OrElse , operand pertama dievaluasi hanya sekali, dan operand kedua tidak dievaluasi atau dievaluasi tepat sekali. Misalnya, pertimbangkan kode berikut:
Module Test
Function TrueValue() As Boolean
Console.Write(" True")
Return True
End Function
Function FalseValue() As Boolean
Console.Write(" False")
Return False
End Function
Sub Main()
Console.Write("And:")
If FalseValue() And TrueValue() Then
End If
Console.WriteLine()
Console.Write("Or:")
If TrueValue() Or FalseValue() Then
End If
Console.WriteLine()
Console.Write("AndAlso:")
If FalseValue() AndAlso TrueValue() Then
End If
Console.WriteLine()
Console.Write("OrElse:")
If TrueValue() OrElse FalseValue() Then
End If
Console.WriteLine()
End Sub
End Module
Ini mencetak hasil berikut:
And: False True
Or: True False
AndAlso: False
OrElse: True
Dalam bentuk AndAlso operator dan OrElse yang diangkat, jika operand pertama adalah null Boolean?, maka operand kedua dievaluasi tetapi hasilnya selalu null Boolean?.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob |
| SB | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | |
| Oleh | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | ||
| Sh | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | |||
| US | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | ||||
| Di | Bo | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | |||||
| UI | Bo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | ||||||
| Lo | Bo | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | |||||||
| UL | Bo | Bo | Bo | Bo | Err | Err | Bo | Ob | ||||||||
| De | Bo | Bo | Bo | Err | Err | Bo | Ob | |||||||||
| Si | Bo | Bo | Err | Err | Bo | Ob | ||||||||||
| Lakukan | Bo | Err | Err | Bo | Ob | |||||||||||
| Da | Err | Err | Err | Err | ||||||||||||
| Ch | Err | Err | Err | |||||||||||||
| St | Bo | Ob | ||||||||||||||
| Ob | Ob |
Operator Shift
Operator << biner dan >> melakukan operasi pergeseran bit.
ShiftOperatorExpression
: Expression '<' '<' LineTerminator? Expression
| Expression '>' '>' LineTerminator? Expression
;
Operator didefinisikan untuk Bytejenis , , SByte, ShortUShort, UInteger, Integer, ULong dan Long . Tidak seperti operator biner lainnya, jenis hasil operasi shift ditentukan seolah-olah operator adalah operator unary hanya dengan operand kiri. Jenis operand kanan harus dikonversi secara implisit ke Integer dan tidak digunakan dalam menentukan jenis hasil operasi.
Operator << menyebabkan bit dalam operand pertama digeser meninggalkan jumlah tempat yang ditentukan oleh jumlah shift. Bit berurutan tinggi di luar rentang jenis hasil dibuang dan posisi bit kosong berurutan rendah tidak terisi.
Operator >> menyebabkan bit dalam operand pertama digeser ke kanan jumlah tempat yang ditentukan oleh jumlah shift. Bit berurutan rendah dibuang dan posisi bit kosong urutan tinggi diatur ke nol jika operand kiri positif atau ke satu jika negatif. Jika operand kiri berjenis Byte, UShort, UInteger, atau ULong bit urutan tinggi kosong diisi nol.
Operator shift menggeser bit representasi yang mendasar dari operand pertama dengan jumlah operand kedua. Jika nilai operand kedua lebih besar dari jumlah bit dalam operand pertama, atau negatif, maka jumlah shift dihitung seperti RightOperand And SizeMask di mana SizeMask adalah:
| Jenis LeftOperand | SizeMask |
|---|---|
Byte, SByte |
7 (&H7) |
UShort, Short |
15 (&HF) |
UInteger, Integer |
31 (&H1F) |
ULong, Long |
63 (&H3F) |
Jika jumlah shift adalah nol, hasil operasi identik dengan nilai operand pertama. Tidak ada luapan yang dimungkinkan dari operasi ini.
Jenis Operasi:
| Bo | SB | Oleh | Sh | US | Di | UI | Lo | UL | De | Si | Lakukan | Da | Ch | St | Ob |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sh | SB | Oleh | Sh | Amerika Serikat | Di dalam | Antarmuka Pengguna | Lo | UL | Lo | Lo | Lo | Err | Err | Lo | Ob |
Ekspresi Boolean
Ekspresi Boolean adalah ekspresi yang dapat diuji untuk melihat apakah itu benar atau jika salah.
BooleanExpression
: Expression
;
Jenis T dapat digunakan dalam ekspresi Boolean jika, dalam urutan preferensi:
TBooleanatauBoolean?Tmemiliki konversi yang melebar keBooleanTmemiliki konversi yang melebar keBoolean?Tmendefinisikan dua operator pseudo,IsTruedanIsFalse.Tmemiliki konversi yang menyempit keBoolean?yang tidak melibatkan konversi dariBooleankeBoolean?.Tmemiliki konversi yang mempersempit keBoolean.
Nota. Menarik untuk dicatat bahwa jika Option Strict tidak aktif, ekspresi yang memiliki konversi Boolean yang mempersempit akan diterima tanpa kesalahan waktu kompilasi tetapi bahasa masih akan lebih memilih IsTrue operator jika ada. Ini karena Option Strict hanya mengubah apa yang dan tidak diterima oleh bahasa, dan tidak pernah mengubah arti ekspresi yang sebenarnya. Dengan demikian, IsTrue harus selalu disukai daripada konversi yang menyempit, terlepas dari Option Strict.
Misalnya, kelas berikut tidak menentukan konversi yang melebar ke Boolean. Akibatnya, penggunaannya dalam If pernyataan menyebabkan panggilan ke IsTrue operator.
Class MyBool
Public Shared Widening Operator CType(b As Boolean) As MyBool
...
End Operator
Public Shared Narrowing Operator CType(b As MyBool) As Boolean
...
End Operator
Public Shared Operator IsTrue(b As MyBool) As Boolean
...
End Operator
Public Shared Operator IsFalse(b As MyBool) As Boolean
...
End Operator
End Class
Module Test
Sub Main()
Dim b As New MyBool
If b Then Console.WriteLine("True")
End Sub
End Module
Jika ekspresi Boolean di ketik sebagai atau dikonversi ke Boolean atau Boolean?, maka itu benar jika nilainya adalah True dan salah sebaliknya.
Jika tidak, ekspresi Boolean memanggil IsTrue operator dan mengembalikan True jika operator mengembalikan True; jika tidak, itu salah (tetapi tidak pernah memanggil IsFalse operator).
Dalam contoh berikut, Integer memiliki konversi yang mempersempit ke Boolean, sehingga null Integer? memiliki konversi yang menyempit ke keduanya Boolean? (menghasilkan null Boolean) dan ke Boolean (yang melemparkan pengecualian). Konversi yang menyempit ke Boolean? lebih disukai, sehingga nilai "i" sebagai ekspresi Boolean adalah False.
Dim i As Integer? = Nothing
If i Then Console.WriteLine()
Ekspresi Lambda
Ekspresi lambda mendefinisikan metode anonim yang disebut metode lambda. Metode Lambda memudahkan untuk meneruskan metode "in-line" ke metode lain yang mengambil jenis delegasi.
LambdaExpression
: SingleLineLambda
| MultiLineLambda
;
SingleLineLambda
: LambdaModifier* 'Function' ( OpenParenthesis ParameterList? CloseParenthesis )? Expression
| 'Sub' ( OpenParenthesis ParameterList? CloseParenthesis )? Statement
;
MultiLineLambda
: MultiLineFunctionLambda
| MultiLineSubLambda
;
MultiLineFunctionLambda
: LambdaModifier? 'Function' ( OpenParenthesis ParameterList? CloseParenthesis )? ( 'As' TypeName )? LineTerminator
Block
'End' 'Function'
;
MultiLineSubLambda
: LambdaModifier? 'Sub' ( OpenParenthesis ParameterList? CloseParenthesis )? LineTerminator
Block
'End' 'Sub'
;
LambdaModifier
: 'Async' | 'Iterator'
;
Contohnya:
Module Test
Delegate Function IntFunc(x As Integer) As Integer
Sub Apply(a() As Integer, func As IntFunc)
For index As Integer = 0 To a.Length - 1
a(index) = func(a(index))
Next index
End Sub
Sub Main()
Dim a() As Integer = { 1, 2, 3, 4 }
Apply(a, Function(x As Integer) x * 2)
For Each value In a
Console.Write(value & " ")
Next value
End Sub
End Module
akan mencetak:
2 4 6 8
Ekspresi lambda dimulai dengan pengubah Async opsional atau Iterator, diikuti oleh kata kunci Function atau Sub dan daftar parameter. Parameter dalam ekspresi lambda tidak dapat dideklarasikan Optional atau ParamArray dan tidak dapat memiliki atribut. Tidak seperti metode reguler, menghilangkan jenis parameter untuk metode lambda tidak secara otomatis menyimpulkan Object. Sebaliknya, ketika metode lambda diklasifikasi ulang, jenis parameter dan ByRef pengubah yang dihilangkan disimpulkan dari jenis target. Dalam contoh sebelumnya, ekspresi lambda dapat ditulis sebagai Function(x) x * 2, dan akan menyimpulkan jenis xInteger menjadi ketika metode lambda digunakan untuk membuat instans jenis IntFunc delegasi. Tidak seperti inferensi variabel lokal, jika parameter metode lambda menghilangkan jenis tetapi memiliki pengubah nama array atau nullable, kesalahan waktu kompilasi terjadi.
Ekspresi lambda reguler adalah ekspresi yang tidak Async memiliki atau pengubahIterator.
Ekspresi lambda iterator adalah satu dengan Iterator pengubah dan tidak ada Async pengubah. Ini harus menjadi fungsi. Ketika diklasifikasi ulang ke nilai, itu hanya dapat diklasifikasi ulang ke nilai jenis delegasi yang jenis pengembaliannya adalah IEnumerator, atau IEnumerable, atau atau IEnumerable(Of T)IEnumerator(Of T) untuk beberapa T, dan yang tidak memiliki parameter ByRef.
Ekspresi lambda asinkron adalah satu dengan pengubah Async dan tanpa Iterator pengubah. Sub lambda asinkron hanya dapat diklasifikasikan ulang ke nilai jenis sub delegasi tanpa parameter ByRef. Fungsi asinkron lambda hanya dapat diklasifikasikan ulang ke nilai jenis delegasi fungsi yang jenis pengembaliannya adalah Task atau Task(Of T) untuk beberapa T, dan yang tidak memiliki parameter ByRef.
Ekspresi Lambda dapat berupa baris tunggal atau multibaris. Ekspresi lambda baris Function tunggal berisi ekspresi tunggal yang mewakili nilai yang dikembalikan dari metode lambda. Ekspresi lambda baris Sub tunggal berisi satu pernyataan tanpa penutupannya StatementTerminator. Contohnya:
Module Test
Sub Do(a() As Integer, action As Action(Of Integer))
For index As Integer = 0 To a.Length - 1
action(a(index))
Next index
End Sub
Sub Main()
Dim a() As Integer = { 1, 2, 3, 4 }
Do(a, Sub(x As Integer) Console.WriteLine(x))
End Sub
End Module
Konstruksi lambda baris tunggal mengikat kurang erat daripada semua ekspresi dan pernyataan lainnya. Jadi, misalnya, "Function() x + 5" setara dengan "Function() (x+5)" daripada "(Function() x) + 5". Untuk menghindari ambiguitas, ekspresi lambda baris Sub tunggal mungkin tidak berisi pernyataan Dim atau pernyataan deklarasi label. Selain itu, kecuali diapit dalam tanda kurung, ekspresi lambda satu baris Sub mungkin tidak segera diikuti oleh titik dua ":", operator akses anggota ".", operator akses anggota kamus "!" atau tanda kurung terbuka "(". Ini mungkin tidak berisi pernyataan blok (With, , SyncLock, If...EndIf, WhileFor, Do, Using) atau .OnErrorResume
Nota. Dalam ekspresi Function(i) x=ilambda , isi ditafsirkan sebagai ekspresi (yang menguji apakah x dan i sama). Tetapi dalam ekspresi Sub(i) x=ilambda , isi ditafsirkan sebagai pernyataan (yang menugaskan i ke x).
Ekspresi lambda multibaris berisi blok pernyataan dan harus diakhiri dengan pernyataan yang sesuai End (yaitu End Function atau End Sub). Seperti halnya metode reguler, metode Function atau pernyataan dan SubEnd pernyataan lambda multibaris harus berada di baris mereka sendiri. Contohnya:
' Error: Function statement must be on its own line!
Dim x = Sub(x As Integer) : Console.WriteLine(x) : End Sub
' OK
Dim y = Sub(x As Integer)
Console.WriteLine(x)
End Sub
Ekspresi lambda multibaris Function dapat mendeklarasikan jenis pengembalian tetapi tidak dapat menempatkan atribut di atasnya. Jika ekspresi lambda multibaris Function tidak mendeklarasikan jenis pengembalian tetapi jenis pengembalian dapat disimpulkan dari konteks di mana ekspresi lambda digunakan , maka jenis pengembalian tersebut digunakan. Jika tidak, jenis pengembalian fungsi dihitung sebagai berikut:
Dalam ekspresi lambda biasa, jenis pengembalian adalah jenis ekspresi dominan di semua
Returnpernyataan dalam blok pernyataan.Dalam ekspresi lambda asinkron, jenis pengembalian adalah
Task(Of T)di manaTadalah jenis ekspresi dominan dalam semuaReturnpernyataan di blok pernyataan.Dalam ekspresi lambda iterator, jenis pengembalian adalah
IEnumerable(Of T)di manaTadalah jenis ekspresi dominan di semuaYieldpernyataan dalam blok pernyataan.
Contohnya:
Function f(min As Integer, max As Integer) As IEnumerable(Of Integer)
If min > max Then Throw New ArgumentException()
Dim x = Iterator Function()
For i = min To max
Yield i
Next
End Function
' infers x to be a delegate with return type IEnumerable(Of Integer)
Return x()
End Function
Dalam semua kasus, jika tidak Return ada pernyataan (masing-masing Yield), atau jika tidak ada jenis dominan di antara mereka, dan semantik ketat sedang digunakan, kesalahan waktu kompilasi terjadi; jika tidak, jenis dominan secara Objectimplisit .
Perhatikan bahwa jenis pengembalian dihitung dari semua Return pernyataan, meskipun tidak dapat dijangkau. Contohnya:
' Return type is Double
Dim x = Function()
Return 10
Return 10.50
End Function
Tidak ada variabel pengembalian implisit, karena tidak ada nama untuk variabel.
Blok pernyataan di dalam ekspresi lambda multibaris memiliki batasan berikut:
On ErrordanResumepernyataan tidak diizinkan, meskipunTrypernyataan diizinkan.Lokal statis tidak dapat dideklarasikan dalam ekspresi lambda multibaris.
Tidak dimungkinkan untuk bercabang ke atau keluar dari blok pernyataan ekspresi lambda multibaris, meskipun aturan percabangan normal berlaku di dalamnya. Contohnya:
Label1: Dim x = Sub() ' Error: Cannot branch out GoTo Label1 ' OK: Wholly within the lamba. GoTo Label2: Label2: End Sub ' Error: Cannot branch in GoTo Label2
Ekspresi lambda kira-kira setara dengan metode anonim yang dideklarasikan pada jenis yang berisi. Contoh awal kira-kira setara dengan:
Module Test
Delegate Function IntFunc(x As Integer) As Integer
Sub Apply(a() As Integer, func As IntFunc)
For index As Integer = 0 To a.Length - 1
a(index) = func(a(index))
Next index
End Sub
Function $Lambda1(x As Integer) As Integer
Return x * 2
End Function
Sub Main()
Dim a() As Integer = { 1, 2, 3, 4 }
Apply(a, AddressOf $Lambda1)
For Each value In a
Console.Write(value & " ")
Next value
End Sub
End Module
Penutupan
Ekspresi Lambda memiliki akses ke semua variabel dalam cakupan, termasuk variabel atau parameter lokal yang ditentukan dalam metode yang berisi dan ekspresi lambda. Ketika ekspresi lambda mengacu pada variabel atau parameter lokal, ekspresi lambda menangkap variabel yang dirujuk ke dalam penutupan. Penutupan adalah objek yang hidup di tumpukan alih-alih pada tumpukan, dan ketika variabel ditangkap, semua referensi ke variabel dialihkan ke penutupan. Ini memungkinkan ekspresi lambda untuk terus merujuk ke variabel dan parameter lokal bahkan setelah metode yang berisi selesai. Contohnya:
Module Test
Delegate Function D() As Integer
Function M() As D
Dim x As Integer = 10
Return Function() x
End Function
Sub Main()
Dim y As D = M()
' Prints 10
Console.WriteLine(y())
End Sub
End Module
kira-kira setara dengan:
Module Test
Delegate Function D() As Integer
Class $Closure1
Public x As Integer
Function $Lambda1() As Integer
Return x
End Function
End Class
Function M() As D
Dim c As New $Closure1()
c.x = 10
Return AddressOf c.$Lambda1
End Function
Sub Main()
Dim y As D = M()
' Prints 10
Console.WriteLine(y())
End Sub
End Module
Penutupan menangkap salinan baru variabel lokal setiap kali memasuki blok tempat variabel lokal dideklarasikan, tetapi salinan baru diinisialisasi dengan nilai salinan sebelumnya, jika ada. Contohnya:
Module Test
Delegate Function D() As Integer
Function M() As D()
Dim a(9) As D
For i As Integer = 0 To 9
Dim x
a(i) = Function() x
x += 1
Next i
Return a
End Function
Sub Main()
Dim y() As D = M()
For i As Integer = 0 To 9
Console.Write(y(i)() & " ")
Next i
End Sub
End Module
Cetakan
1 2 3 4 5 6 7 8 9 10
Melainkan
9 9 9 9 9 9 9 9 9 9
Karena penutupan harus diinisialisasi saat memasuki blok, tidak diizinkan untuk masuk ke GoTo blok dengan penutupan dari luar blok itu, meskipun diizinkan untuk masuk ke Resume blok dengan penutupan. Contohnya:
Module Test
Sub Main()
Dim a = 10
If a = 10 Then
L1:
Dim x = Function() a
' Valid, source is within block
GoTo L2
L2:
End If
' ERROR: target is inside block with closure
GoTo L1
End Sub
End Module
Karena tidak dapat ditangkap ke dalam penutupan, berikut ini tidak dapat muncul di dalam ekspresi lambda:
Parameter referensi.
Ekspresi instans (
Me,MyClass,MyBase), jika jenisnyaMebukan kelas.
Anggota ekspresi pembuatan jenis anonim, jika ekspresi lambda adalah bagian dari ekspresi. Contohnya:
' Error: Lambda cannot refer to anonymous type field
Dim x = New With { .a = 12, .b = Function() .a }
ReadOnly variabel instans dalam konstruktor instans atau ReadOnly variabel bersama di konstruktor bersama di mana variabel digunakan dalam konteks non-nilai. Contohnya:
Class C1
ReadOnly F1 As Integer
Sub New()
' Valid, doesn't modify F1
Dim x = Function() F1
' Error, tries to modify F1
Dim f = Function() ModifyValue(F1)
End Sub
Sub ModifyValue(ByRef x As Integer)
End Sub
End Class
Ekspresi Kueri
Ekspresi kueri adalah ekspresi yang menerapkan serangkaian operator kueri ke elemen koleksi yang dapat dikueri. Misalnya, ekspresi berikut mengambil kumpulan Customer objek dan mengembalikan nama semua pelanggan di negara bagian Washington:
Dim names = _
From cust In Customers _
Where cust.State = "WA" _
Select cust.Name
Ekspresi kueri harus dimulai dengan From operator atau Aggregate dan dapat diakhir dengan operator kueri apa pun. Hasil ekspresi kueri diklasifikasikan sebagai nilai; jenis hasil ekspresi bergantung pada jenis hasil operator kueri terakhir dalam ekspresi.
QueryExpression
: FromOrAggregateQueryOperator QueryOperator*
;
FromOrAggregateQueryOperator
: FromQueryOperator
| AggregateQueryOperator
;
QueryOperator
: FromQueryOperator
| AggregateQueryOperator
| SelectQueryOperator
| DistinctQueryOperator
| WhereQueryOperator
| OrderByQueryOperator
| PartitionQueryOperator
| LetQueryOperator
| GroupByQueryOperator
| JoinOrGroupJoinQueryOperator
;
JoinOrGroupJoinQueryOperator
: JoinQueryOperator
| GroupJoinQueryOperator
;
Variabel Rentang
Beberapa operator kueri memperkenalkan jenis variabel khusus yang disebut variabel rentang. Variabel rentang bukan variabel nyata; sebaliknya, mereka mewakili nilai individual selama evaluasi kueri atas koleksi input.
CollectionRangeVariableDeclarationList
: CollectionRangeVariableDeclaration ( Comma CollectionRangeVariableDeclaration )*
;
CollectionRangeVariableDeclaration
: Identifier ( 'As' TypeName )? 'In' LineTerminator? Expression
;
ExpressionRangeVariableDeclarationList
: ExpressionRangeVariableDeclaration ( Comma ExpressionRangeVariableDeclaration )*
;
ExpressionRangeVariableDeclaration
: Identifier ( 'As' TypeName )? Equals Expression
;
Variabel rentang dilingkup dari operator kueri pengenalan ke akhir ekspresi kueri, atau ke operator kueri seperti Select yang menyembunyikannya. Misalnya, dalam kueri berikut
Dim waCusts = _
From cust As Customer In Customers _
Where cust.State = "WA"
From operator kueri memperkenalkan variabel cust rentang yang ditik sebagai Customer yang mewakili setiap pelanggan dalam Customers koleksi. Operator kueri berikut Where kemudian merujuk ke variabel cust rentang dalam ekspresi filter untuk menentukan apakah akan memfilter pelanggan individual dari koleksi yang dihasilkan.
Ada dua jenis variabel rentang: variabel rentang koleksi dan variabel rentang ekspresi. Variabel rentang koleksi mengambil nilainya dari elemen koleksi yang sedang dikueri. Ekspresi koleksi dalam deklarasi variabel rentang koleksi harus diklasifikasikan sebagai nilai yang jenisnya dapat dikueri. Jika jenis variabel rentang koleksi dihilangkan, variabel tersebut disimpulkan sebagai jenis elemen ekspresi koleksi, atau Object jika ekspresi koleksi tidak memiliki jenis elemen (yaitu hanya mendefinisikan Cast metode). Jika ekspresi koleksi tidak dapat dikueri (yaitu jenis elemen koleksi tidak dapat disimpulkan), hasil kesalahan waktu kompilasi.
Variabel rentang ekspresi adalah variabel rentang yang nilainya dihitung oleh ekspresi daripada koleksi. Dalam contoh berikut, Select operator kueri memperkenalkan variabel rentang ekspresi bernama cityState dihitung dari dua bidang:
Dim cityStates = _
From cust As Customer In Customers _
Select cityState = cust.City & "," & cust.State _
Where cityState.Length() < 10
Variabel rentang ekspresi tidak diperlukan untuk mereferensikan variabel rentang lain, meskipun variabel tersebut mungkin bernilai meragukan. Ekspresi yang ditetapkan ke variabel rentang ekspresi harus diklasifikasikan sebagai nilai dan harus secara implisit dapat dikonversi ke jenis variabel rentang, jika diberikan.
Hanya di operator Let mungkin variabel rentang ekspresi memiliki jenis yang ditentukan. Di operator lain, atau jika jenisnya tidak ditentukan, inferensi jenis variabel lokal digunakan untuk menentukan jenis variabel rentang.
Variabel rentang harus mengikuti aturan untuk mendeklarasikan variabel lokal sehubungan dengan bayangan. Dengan demikian, variabel rentang tidak dapat menyembunyikan nama variabel atau parameter lokal dalam metode penutup atau variabel rentang lain (kecuali operator kueri secara khusus menyembunyikan semua variabel rentang saat ini dalam cakupan).
Tipe yang Dapat Dikueri
Ekspresi kueri diimplementasikan dengan menerjemahkan ekspresi ke dalam panggilan ke metode terkenal pada jenis koleksi. Metode yang ditentukan dengan baik ini menentukan jenis elemen koleksi yang dapat dikueri serta jenis hasil operator kueri yang dijalankan pada koleksi. Setiap operator kueri menentukan metode atau metode yang umumnya diterjemahkan operator kueri, meskipun terjemahan tertentu bergantung pada implementasi. Metode diberikan dalam spesifikasi menggunakan format umum yang terlihat seperti:
Function Select(selector As Func(Of T, R)) As CR
Berikut ini berlaku untuk metode:
Metode harus merupakan instans atau anggota ekstensi dari jenis koleksi dan harus dapat diakses.
Metode ini mungkin umum, asalkan dimungkinkan untuk menyimpulkan semua argumen jenis.
Metode ini mungkin kelebihan beban, dalam hal ini resolusi kelebihan beban digunakan untuk menentukan metode yang tepat untuk digunakan.
Jenis delegasi lain dapat digunakan sebagai pengganti jenis delegasi
Func, asalkan memiliki tanda tangan yang sama, termasuk jenis pengembalian, sebagai jenis yangFunccocok.Jenis
System.Linq.Expressions.Expression(Of D)dapat digunakan sebagai pengganti jenis delegasiFunc, asalkanDmerupakan jenis delegasi yang memiliki tanda tangan yang sama, termasuk jenis pengembalian, sebagai jenis yangFunccocok.Jenis
Tmewakili jenis elemen koleksi input. Semua metode yang ditentukan oleh jenis koleksi harus memiliki jenis elemen input yang sama agar jenis koleksi dapat dikueri.Jenis
Smewakili jenis elemen dari koleksi input kedua dalam kasus operator kueri yang melakukan gabungan.Jenis
Kmewakili jenis kunci dalam kasus operator kueri yang memiliki sekumpulan variabel rentang yang bertindak sebagai kunci.Jenis
Nmewakili jenis yang digunakan sebagai jenis numerik (meskipun masih bisa menjadi jenis yang ditentukan pengguna dan bukan jenis numerik intrinsik).Jenis
Bmewakili jenis yang dapat digunakan dalam ekspresi Boolean.Jenis
Rmewakili jenis elemen koleksi hasil, jika operator kueri menghasilkan kumpulan hasil.Rtergantung pada jumlah variabel rentang dalam cakupan pada kesimpulan operator kueri. Jika variabel rentang tunggal berada dalam cakupan, makaRadalah jenis variabel rentang tersebut. Dalam contohDim custNames = From c In Customers Select c.Namehasil kueri akan menjadi jenis koleksi dengan jenis
Stringelemen . Jika beberapa variabel rentang berada dalam cakupan, makaRadalah jenis anonim yang berisi semua variabel rentang dalam cakupan sebagaiKeybidang. Dalam contoh:Dim custNames = From c In Customers, o In c.Orders Select Name = c.Name, ProductName = o.ProductNamehasil kueri akan menjadi jenis koleksi dengan tipe elemen tipe anonim dengan properti baca-saja bernama
NamejenisStringdan properti baca-saja bernamaProductNametipeString.Dalam ekspresi kueri, jenis anonim yang dihasilkan untuk berisi variabel rentang transparan, yang berarti bahwa variabel rentang selalu tersedia tanpa kualifikasi. Misalnya, dalam contoh sebelumnya variabel
crentang danodapat diakses tanpa kualifikasi diSelectoperator kueri, meskipun jenis elemen koleksi input adalah jenis anonim.Jenis
CXmewakili jenis koleksi, belum tentu jenis koleksi input, yang jenis elemennya adalah beberapa jenisX.
Jenis koleksi yang dapat dikueri harus memenuhi salah satu kondisi berikut, sesuai urutan preferensi:
Ini harus menentukan metode yang sesuai
Select.Ini harus memiliki salah satu metode berikut
Function AsEnumerable() As CT Function AsQueryable() As CTyang dapat dipanggil untuk mendapatkan koleksi yang dapat dikueri. Jika kedua metode disediakan,
AsQueryablelebih disukai daripadaAsEnumerable.Ini harus memiliki metode
Function Cast(Of T)() As CTyang dapat dipanggil dengan jenis variabel rentang untuk menghasilkan koleksi yang dapat dikueri.
Karena menentukan jenis elemen koleksi terjadi secara independen dari pemanggilan metode aktual, penerapan metode tertentu tidak dapat ditentukan. Dengan demikian, ketika menentukan jenis elemen koleksi jika ada metode instans yang cocok dengan metode terkenal, maka metode ekstensi apa pun yang cocok dengan metode terkenal diabaikan.
Terjemahan operator kueri terjadi dalam urutan operator kueri terjadi dalam ekspresi. Objek koleksi tidak diperlukan untuk menerapkan semua metode yang diperlukan oleh semua operator kueri, meskipun setiap objek koleksi setidaknya harus mendukung Select operator kueri. Jika metode yang diperlukan tidak ada, kesalahan waktu kompilasi terjadi. Saat mengikat nama metode terkenal, non-metode diabaikan untuk tujuan beberapa warisan dalam antarmuka dan pengikatan metode ekstensi, meskipun semantik bayangan masih berlaku. Contohnya:
Class Q1
Public Function [Select](selector As Func(Of Integer, Integer)) As Q1
End Function
End Class
Class Q2
Inherits Q1
Public [Select] As Integer
End Class
Module Test
Sub Main()
Dim qs As New Q2()
' Error: Q2.Select still hides Q1.Select
Dim zs = From q In qs Select q
End Sub
End Module
Pengindeks Kueri Default
Setiap jenis koleksi yang dapat dikueri yang jenis elemennya dan T belum memiliki properti default dianggap memiliki properti default dari formulir umum berikut:
Public ReadOnly Default Property Item(index As Integer) As T
Get
Return Me.ElementAtOrDefault(index)
End Get
End Property
Properti default hanya dapat dirujuk menggunakan sintaks akses properti default; properti default tidak dapat dirujuk berdasarkan nama. Contohnya:
Dim customers As IEnumerable(Of Customer) = ...
Dim customerThree = customers(2)
' Error, no such property
Dim customerFour = customers.Item(4)
Jika jenis koleksi tidak memiliki ElementAtOrDefault anggota, kesalahan waktu kompilasi akan terjadi.
Dari Operator Kueri
Operator From kueri memperkenalkan variabel rentang koleksi yang mewakili masing-masing anggota koleksi yang akan dikueri.
FromQueryOperator
: LineTerminator? 'From' LineTerminator? CollectionRangeVariableDeclarationList
;
Misalnya, ekspresi kueri:
From c As Customer In Customers ...
dapat dianggap setara dengan
For Each c As Customer In Customers
...
Next c
From Saat operator kueri mendeklarasikan beberapa variabel rentang koleksi atau bukan operator kueri pertama From dalam ekspresi kueri, setiap variabel rentang koleksi baru digabungkan silang ke kumpulan variabel rentang yang ada. Hasilnya adalah bahwa kueri dievaluasi atas lintas produk dari semua elemen dalam koleksi yang bergabung. Misalnya, ekspresi:
From c In Customers _
From e In Employees _
...
dapat dianggap setara dengan:
For Each c In Customers
For Each e In Employees
...
Next e
Next c
dan sama persis dengan:
From c In Customers, e In Employees ...
Variabel rentang yang diperkenalkan di operator kueri sebelumnya dapat digunakan di operator kueri selanjutnya From . Misalnya, dalam ekspresi kueri berikut, operator kueri kedua From mengacu pada nilai variabel rentang pertama:
From c As Customer In Customers _
From o As Order In c.Orders _
Select c.Name, o
Beberapa variabel rentang dalam From operator kueri atau beberapa From operator kueri hanya didukung jika jenis koleksi berisi satu atau kedua metode berikut:
Function SelectMany(selector As Func(Of T, CR)) As CR
Function SelectMany(selector As Func(Of T, CS), _
resultsSelector As Func(Of T, S, R)) As CR
Kode
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = From x In xs, y In ys ...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = _
xs.SelectMany( _
Function(x As Integer) ys, _
Function(x As Integer, y As Integer) New With {x, y})...
Nota.
From bukan kata yang dipesan.
Gabungkan Operator Kueri
Operator Join kueri menggabungkan variabel rentang yang ada dengan variabel rentang koleksi baru, menghasilkan satu koleksi yang elemennya telah digabungkan berdasarkan ekspresi kesetaraan.
JoinQueryOperator
: LineTerminator? 'Join' LineTerminator? CollectionRangeVariableDeclaration
JoinOrGroupJoinQueryOperator? LineTerminator? 'On' LineTerminator? JoinConditionList
;
JoinConditionList
: JoinCondition ( 'And' LineTerminator? JoinCondition )*
;
JoinCondition
: Expression 'Equals' LineTerminator? Expression
;
Contohnya:
Dim customersAndOrders = _
From cust In Customers _
Join ord In Orders On cust.ID Equals ord.CustomerID
Ekspresi kesetaraan lebih dibatasi daripada ekspresi kesetaraan reguler:
Kedua ekspresi harus diklasifikasikan sebagai nilai.
Kedua ekspresi harus mereferensikan setidaknya satu variabel rentang.
Variabel rentang yang dideklarasikan dalam operator kueri gabungan harus direferensikan oleh salah satu ekspresi, dan ekspresi tersebut tidak boleh mereferensikan variabel rentang lainnya.
Jika jenis dua ekspresi bukan jenis yang sama persis, maka
Jika operator kesetaraan didefinisikan untuk dua jenis, kedua ekspresi secara implisit dapat dikonversi ke dalamnya, dan bukan
Object, maka konversi kedua ekspresi ke jenis tersebut.Jika tidak, jika ada jenis dominan yang kedua ekspresi dapat dikonversi secara implisit, maka konversi kedua ekspresi ke jenis tersebut.
Jika tidak, terjadi kesalahan waktu kompilasi.
Ekspresi dibandingkan menggunakan nilai hash (yaitu dengan memanggil GetHashCode()) daripada menggunakan operator kesetaraan untuk efisiensi. Operator Join kueri dapat melakukan beberapa gabungan atau kondisi kesetaraan di operator yang sama.
Join Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Join(inner As CS, _
outerSelector As Func(Of T, K), _
innerSelector As Func(Of S, K), _
resultSelector As Func(Of T, S, R)) As CR
Kode
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = From x In xs _
Join y In ys On x Equals y _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = _
xs.Join( _
ys, _
Function(x As Integer) x, _
Function(y As Integer) y, _
Function(x As Integer, y As Integer) New With {x, y})...
Catatan.Join, On dan Equals bukan kata yang dipesan.
Biarkan Operator Kueri
Operator Let kueri memperkenalkan variabel rentang ekspresi. Ini memungkinkan pengkalkulasian nilai perantara setelah yang akan digunakan beberapa kali di operator kueri nanti.
LetQueryOperator
: LineTerminator? 'Let' LineTerminator? ExpressionRangeVariableDeclarationList
;
Contohnya:
Dim taxedPrices = _
From o In Orders _
Let tax = o.Price * 0.088 _
Where tax > 3.50 _
Select o.Price, tax, total = o.Price + tax
dapat dianggap setara dengan:
For Each o In Orders
Dim tax = o.Price * 0.088
...
Next o
Let Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Select(selector As Func(Of T, R)) As CR
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Let y = x * 10 _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.Select(Function(x As Integer) New With {x, .y = x * 10})...
Pilih Operator Kueri
Operator Select kueri seperti Let operator kueri karena memperkenalkan variabel rentang ekspresi; namun, Select operator kueri menyembunyikan variabel rentang yang saat ini tersedia alih-alih menambahkannya. Selain itu, jenis variabel rentang ekspresi yang diperkenalkan oleh Select operator kueri selalu disimpulkan menggunakan aturan inferensi jenis variabel lokal; jenis eksplisit tidak dapat ditentukan, dan jika tidak ada jenis yang dapat disimpulkan, kesalahan waktu kompilasi terjadi.
SelectQueryOperator
: LineTerminator? 'Select' LineTerminator? ExpressionRangeVariableDeclarationList
;
Misalnya, dalam kueri:
Dim smiths = _
From cust In Customers _
Select name = cust.name _
Where name.EndsWith("Smith")
Where operator kueri hanya memiliki akses ke variabel rentang yang name diperkenalkan oleh Select operator; jika Where operator telah mencoba mereferensikan cust, kesalahan waktu kompilasi akan terjadi.
Alih-alih secara eksplisit menentukan nama variabel rentang, Select operator kueri dapat menyimpulkan nama variabel rentang, menggunakan aturan yang sama dengan ekspresi pembuatan objek jenis anonim. Contohnya:
Dim custAndOrderNames = _
From cust In Customers, ord In cust.Orders _
Select cust.name, ord.ProductName _
Where name.EndsWith("Smith")
Jika nama variabel rentang tidak disediakan dan nama tidak dapat disimpulkan, kesalahan waktu kompilasi terjadi.
Select Jika operator kueri hanya berisi ekspresi tunggal, tidak ada kesalahan yang terjadi jika nama untuk variabel rentang tersebut tidak dapat disimpulkan tetapi variabel rentang tidak bernama. Contohnya:
Dim custAndOrderNames = _
From cust In Customers, ord In cust.Orders _
Select cust.Name & " bought " & ord.ProductName _
Take 10
Jika ada ambiguitas dalam Select operator kueri antara menetapkan nama ke variabel rentang dan ekspresi kesetaraan, penetapan nama lebih disukai. Contohnya:
Dim badCustNames = _
From c In Customers _
Let name = "John Smith" _
Select name = c.Name ' Creates a range variable named "name"
Dim goodCustNames = _
From c In Customers _
Let name = "John Smith" _
Select match = (name = c.Name)
Setiap ekspresi dalam Select operator kueri harus diklasifikasikan sebagai nilai.
Select Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Select(selector As Func(Of T, R)) As CR
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Select x, y = x * 10 _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.Select(Function(x As Integer) New With {x, .y = x * 10})...
Operator Kueri Yang Berbeda
Operator Distinct kueri membatasi nilai dalam koleksi hanya untuk yang memiliki nilai berbeda, seperti yang ditentukan dengan membandingkan jenis elemen untuk kesetaraan.
DistinctQueryOperator
: LineTerminator? 'Distinct' LineTerminator?
;
Misalnya, kueri:
Dim distinctCustomerPrice = _
From cust In Customers, ord In cust.Orders _
Select cust.Name, ord.Price _
Distinct
hanya akan mengembalikan satu baris untuk setiap pasangan yang berbeda dari nama pelanggan dan harga pesanan, bahkan jika pelanggan memiliki beberapa pesanan dengan harga yang sama.
Distinct Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Distinct() As CT
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Distinct _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = xs.Distinct()...
Nota.
Distinct bukan kata yang dipesan.
Di mana Operator Kueri
Operator Where kueri membatasi nilai dalam koleksi untuk yang memenuhi kondisi tertentu.
WhereQueryOperator
: LineTerminator? 'Where' LineTerminator? BooleanExpression
;
Where Operator kueri mengambil ekspresi Boolean yang dievaluasi untuk setiap set nilai variabel rentang; jika nilai ekspresi benar, maka nilai muncul dalam koleksi output, jika tidak, nilai dilewati. Misalnya, ekspresi kueri:
From cust In Customers, ord In Orders _
Where cust.ID = ord.CustomerID _
...
dapat dianggap setara dengan perulangan berlapis
For Each cust In Customers
For Each ord In Orders
If cust.ID = ord.CustomerID Then
...
End If
Next ord
Next cust
Where Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Where(predicate As Func(Of T, B)) As CT
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Where x < 10 _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.Where(Function(x As Integer) x < 10)...
Nota.
Where bukan kata yang dipesan.
Operator Kueri Partisi
PartitionQueryOperator
: LineTerminator? 'Take' LineTerminator? Expression
| LineTerminator? 'Take' 'While' LineTerminator? BooleanExpression
| LineTerminator? 'Skip' LineTerminator? Expression
| LineTerminator? 'Skip' 'While' LineTerminator? BooleanExpression
;
Operator Take kueri menghasilkan elemen pertama n koleksi. Saat digunakan dengan pengubah While , Take operator menghasilkan elemen pertama n dari koleksi yang memenuhi ekspresi Boolean. Operator Skip melewati elemen pertama n koleksi lalu mengembalikan sisa koleksi. Ketika digunakan bersama dengan pengubah While , Skip operator melewati elemen pertama n dari koleksi yang memenuhi ekspresi Boolean dan kemudian mengembalikan sisa koleksi. Ekspresi dalam Take operator atau Skip kueri harus diklasifikasikan sebagai nilai.
Take Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Take(count As N) As CT
Skip Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function Skip(count As N) As CT
Take While Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function TakeWhile(predicate As Func(Of T, B)) As CT
Skip While Operator kueri hanya didukung jika jenis koleksi berisi metode:
Function SkipWhile(predicate As Func(Of T, B)) As CT
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Skip 10 _
Take 5 _
Skip While x < 10 _
Take While x > 5 _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.Skip(10). _
Take(5). _
SkipWhile(Function(x) x < 10). _
TakeWhile(Function(x) x > 5)...
Nota.
Take dan Skip bukan kata-kata yang dicadangkan.
Operator Urutan menurut Kueri
Operator Order By kueri mengurutkan nilai yang muncul dalam variabel rentang.
OrderByQueryOperator
: LineTerminator? 'Order' 'By' LineTerminator? OrderExpressionList
;
OrderExpressionList
: OrderExpression ( Comma OrderExpression )*
;
OrderExpression
: Expression Ordering?
;
Ordering
: 'Ascending' | 'Descending'
;
Order By Operator kueri mengambil ekspresi yang menentukan nilai kunci yang harus digunakan untuk mengurutkan variabel iterasi. Misalnya, kueri berikut mengembalikan produk yang diurutkan berdasarkan harga:
Dim productsByPrice = _
From p In Products _
Order By p.Price _
Select p.Name
Pengurutan dapat ditandai sebagai Ascending, dalam hal ini nilai yang lebih kecil datang sebelum nilai yang lebih besar, atau Descending, dalam hal ini nilai yang lebih besar datang sebelum nilai yang lebih kecil. Default untuk pemesanan jika tidak ada yang ditentukan adalah Ascending. Misalnya, kueri berikut mengembalikan produk yang diurutkan berdasarkan harga dengan produk termahal terlebih dahulu:
Dim productsByPriceDesc = _
From p In Products _
Order By p.Price Descending _
Select p.Name
Operator Order By kueri dapat menentukan beberapa ekspresi untuk pengurutan, dalam hal ini koleksi diurutkan secara berlapis. Misalnya, kueri berikut memesan pelanggan berdasarkan negara bagian, lalu berdasarkan kota dalam setiap negara bagian lalu dengan kode pos dalam setiap kota:
Dim customersByLocation = _
From c In Customers _
Order By c.State, c.City, c.ZIP _
Select c.Name, c.State, c.City, c.ZIP
Ekspresi dalam Order By operator kueri harus diklasifikasikan sebagai nilai. Operator Order By kueri hanya didukung jika jenis koleksi berisi satu atau kedua metode berikut:
Function OrderBy(keySelector As Func(Of T, K)) As CT
Function OrderByDescending(keySelector As Func(Of T, K)) As CT
Jenis CT pengembalian harus berupa koleksi yang diurutkan. Koleksi yang diurutkan adalah jenis koleksi yang berisi satu atau kedua metode:
Function ThenBy(keySelector As Func(Of T, K)) As CT
Function ThenByDescending(keySelector As Func(Of T, K)) As CT
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Order By x Ascending, x Mod 2 Descending _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.OrderBy(Function(x) x).ThenByDescending(Function(x) x Mod 2)...
Nota. Karena operator kueri hanya memetakan sintaksis ke metode yang menerapkan operasi kueri tertentu, pelestarian pesanan tidak ditentukan oleh bahasa dan ditentukan oleh implementasi operator itu sendiri. Ini sangat mirip dengan operator yang ditentukan pengguna karena implementasi untuk membebani operator penambahan untuk jenis numerik yang ditentukan pengguna mungkin tidak melakukan sesuatu yang menyerupai penambahan. Tentu saja, untuk mempertahankan prediktabilitas, menerapkan sesuatu yang tidak sesuai dengan harapan pengguna tidak disarankan.
Nota.
Order dan By bukan kata-kata yang dicadangkan.
Operator Kelompokkan Menurut Kueri
Operator Group By kueri mengelompokkan variabel rentang dalam cakupan berdasarkan satu atau beberapa ekspresi, lalu menghasilkan variabel rentang baru berdasarkan pengelompokan tersebut.
GroupByQueryOperator
: LineTerminator? 'Group' ( LineTerminator? ExpressionRangeVariableDeclarationList )?
LineTerminator? 'By' LineTerminator? ExpressionRangeVariableDeclarationList
LineTerminator? 'Into' LineTerminator? ExpressionRangeVariableDeclarationList
;
Misalnya, kueri berikut mengelompokkan semua pelanggan menurut State, lalu menghitung jumlah dan usia rata-rata setiap grup:
Dim averageAges = _
From cust In Customers _
Group By cust.State _
Into Count(), Average(cust.Age)
Operator Group By kueri memiliki tiga klausa: klausa opsional Group , By klausa, dan Into klausa. Klausa Group memiliki sintaks dan efek yang sama dengan Select operator kueri, kecuali hanya memengaruhi variabel rentang yang tersedia dalam Into klausa dan bukan By klausa. Contohnya:
Dim averageAges = _
From cust In Customers _
Group cust.Age By cust.State _
Into Count(), Average(Age)
Klausa By mendeklarasikan variabel rentang ekspresi yang digunakan sebagai nilai kunci dalam operasi pengelompokan. Klausa Into memungkinkan deklarasi variabel rentang ekspresi yang menghitung agregasi atas setiap grup yang dibentuk oleh By klausa.
Into Dalam klausa, variabel rentang ekspresi hanya dapat ditetapkan ekspresi yang merupakan pemanggilan metode fungsi agregat. Fungsi agregat adalah fungsi pada jenis koleksi grup (yang mungkin belum tentu merupakan jenis koleksi yang sama dari koleksi asli) yang terlihat seperti salah satu metode berikut:
Function _name_() As _type_
Function _name_(selector As Func(Of T, R)) As R
Jika fungsi agregat mengambil argumen delegasi, maka ekspresi pemanggilan dapat memiliki ekspresi argumen yang harus diklasifikasikan sebagai nilai. Ekspresi argumen dapat menggunakan variabel rentang yang berada dalam cakupan; dalam panggilan ke fungsi agregat, variabel rentang tersebut mewakili nilai dalam grup yang sedang dibentuk, bukan semua nilai dalam koleksi. Misalnya, dalam contoh asli di bagian Average ini fungsi menghitung rata-rata usia pelanggan per status daripada untuk semua pelanggan bersama-sama.
Semua jenis koleksi dianggap memiliki fungsi Group agregat yang ditentukan di dalamnya, yang tidak mengambil parameter dan hanya mengembalikan grup. Fungsi agregat standar lainnya yang dapat disediakan oleh jenis koleksi adalah:
Count dan LongCount, yang mengembalikan jumlah elemen dalam grup atau jumlah elemen dalam grup yang memenuhi ekspresi Boolean.
Count dan LongCount hanya didukung jika jenis koleksi berisi salah satu metode:
Function Count() As N
Function Count(selector As Func(Of T, B)) As N
Function LongCount() As N
Function LongCount(selector As Func(Of T, B)) As N
Sum, yang mengembalikan jumlah ekspresi di semua elemen dalam grup.
Sum hanya didukung jika jenis koleksi berisi salah satu metode:
Function Sum() As N
Function Sum(selector As Func(Of T, N)) As N
Min yang mengembalikan nilai minimum ekspresi di semua elemen dalam grup.
Min hanya didukung jika jenis koleksi berisi salah satu metode:
Function Min() As N
Function Min(selector As Func(Of T, N)) As N
Max, yang mengembalikan nilai maksimum ekspresi di semua elemen dalam grup.
Max hanya didukung jika jenis koleksi berisi salah satu metode:
Function Max() As N
Function Max(selector As Func(Of T, N)) As N
Average, yang mengembalikan rata-rata ekspresi di semua elemen dalam grup.
Average hanya didukung jika jenis koleksi berisi salah satu metode:
Function Average() As N
Function Average(selector As Func(Of T, N)) As N
Any, yang menentukan apakah grup berisi anggota atau apakah ekspresi Boolean benar untuk elemen apa pun dalam grup.
Any mengembalikan nilai yang dapat digunakan dalam ekspresi Boolean dan hanya didukung jika jenis koleksi berisi salah satu metode:
Function Any() As B
Function Any(predicate As Func(Of T, B)) As B
All, yang menentukan apakah ekspresi Boolean benar untuk semua elemen dalam grup.
All mengembalikan nilai yang dapat digunakan dalam ekspresi Boolean dan hanya didukung jika jenis koleksi berisi metode:
Function All(predicate As Func(Of T, B)) As B
Group By Setelah operator kueri, variabel rentang yang sebelumnya dalam cakupan disembunyikan, dan variabel rentang yang diperkenalkan oleh By klausul dan Into tersedia.
Group By Operator kueri hanya didukung jika jenis koleksi berisi metode :
Function GroupBy(keySelector As Func(Of T, K), _
resultSelector As Func(Of K, CT, R)) As CR
Deklarasi variabel rentang dalam Group klausul hanya didukung jika jenis koleksi berisi metode :
Function GroupBy(keySelector As Func(Of T, K), _
elementSelector As Func(Of T, S), _
resultSelector As Func(Of K, CS, R)) As CR
Kode
Dim xs() As Integer = ...
Dim zs = From x In xs _
Group y = x * 10, z = x / 10 By evenOdd = x Mod 2 _
Into Sum(y), Average(z) _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.GroupBy( _
Function(x As Integer) x Mod 2, _
Function(x As Integer) New With {.y = x * 10, .z = x / 10}, _
Function(evenOdd, group) New With { _
evenOdd, _
.Sum = group.Sum(Function(e) e.y), _
.Average = group.Average(Function(e) e.z)})...
Catatan.Group, By, dan Into bukan kata yang dipesan.
Operator Kueri Agregat
Operator Aggregate kueri melakukan fungsi Group By serupa dengan operator, kecuali memungkinkan agregasi atas grup yang telah terbentuk. Karena grup telah terbentuk, klausa Aggregate operator kueri tidak menyembunyikan variabel rentang dalam cakupan (dengan cara ini, Aggregate lebih seperti Let, dan Group By lebih seperti Select).Into
AggregateQueryOperator
: LineTerminator? 'Aggregate' LineTerminator? CollectionRangeVariableDeclaration QueryOperator*
LineTerminator? 'Into' LineTerminator? ExpressionRangeVariableDeclarationList
;
Misalnya, kueri berikut mengagregasi total semua pesanan yang dilakukan oleh pelanggan di Washington:
Dim orderTotals = _
From cust In Customers _
Where cust.State = "WA" _
Aggregate order In cust.Orders _
Into Sum(order.Total)
Hasil kueri ini adalah koleksi yang jenis elemennya adalah jenis anonim dengan properti bernama cust di ketik sebagai Customer dan properti bernama Sum dititik sebagai Integer.
Tidak seperti Group By, operator kueri tambahan dapat ditempatkan di Aggregate antara klausul dan Into .
Aggregate Antara klausa dan akhir Into klausul, semua variabel rentang dalam cakupan, termasuk yang dideklarasikan oleh Aggregate klausul dapat digunakan. Misalnya, kueri berikut mengagregasi jumlah total semua pesanan yang dilakukan oleh pelanggan di Washington sebelum 2006:
Dim orderTotals = _
From cust In Customers _
Where cust.State = "WA" _
Aggregate order In cust.Orders _
Where order.Date <= #01/01/2006# _
Into Sum = Sum(order.Total)
Operator Aggregate juga dapat digunakan untuk memulai ekspresi kueri. Dalam hal ini, hasil ekspresi kueri akan menjadi nilai tunggal yang dihitung oleh Into klausa. Misalnya, kueri berikut menghitung jumlah semua total pesanan sebelum 1 Januari 2006:
Dim ordersTotal = _
Aggregate order In Orders _
Where order.Date <= #01/01/2006# _
Into Sum(order.Total)
Hasil kueri adalah nilai tunggal Integer .
Aggregate Operator kueri selalu tersedia (meskipun fungsi agregat juga harus tersedia agar ekspresi valid). Kode
Dim xs() As Integer = ...
Dim zs = _
Aggregate x In xs _
Where x < 5 _
Into Sum()
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim zs = _
xs.Where(Function(x) x < 5).Sum()
Nota.
Aggregate dan Into bukan kata-kata yang dicadangkan.
Operator Kueri Gabungan Grup
Operator Group Join kueri menggabungkan fungsi Join operator kueri dan Group By ke dalam satu operator.
Group Join menggabungkan dua koleksi berdasarkan kunci yang cocok yang diekstrak dari elemen, mengelompokkan semua elemen di sisi kanan gabungan yang cocok dengan elemen tertentu di sisi kiri gabungan. Dengan demikian, operator menghasilkan serangkaian hasil hierarkis.
GroupJoinQueryOperator
: LineTerminator? 'Group' 'Join' LineTerminator? CollectionRangeVariableDeclaration
JoinOrGroupJoinQueryOperator? LineTerminator? 'On' LineTerminator? JoinConditionList
LineTerminator? 'Into' LineTerminator? ExpressionRangeVariableDeclarationList
;
Misalnya, kueri berikut menghasilkan elemen yang berisi satu nama pelanggan, sekelompok semua pesanan mereka, dan jumlah total semua pesanan tersebut:
Dim custsWithOrders = _
From cust In Customers _
Group Join order In Orders On cust.ID Equals order.CustomerID _
Into Orders = Group, OrdersTotal = Sum(order.Total) _
Select cust.Name, Orders, OrdersTotal
Hasil kueri adalah koleksi yang jenis elemennya adalah jenis anonim dengan tiga properti: Name, di ketik sebagai String, Orders di ketik sebagai koleksi yang jenis elemennya adalah Order, dan OrdersTotal, di ketik sebagai Integer.
Group Join Operator kueri hanya didukung jika jenis koleksi berisi metode :
Function GroupJoin(inner As CS, _
outerSelector As Func(Of T, K), _
innerSelector As Func(Of S, K), _
resultSelector As Func(Of T, CS, R)) As CR
Kode
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = From x In xs _
Group Join y in ys On x Equals y _
Into g = Group _
...
umumnya diterjemahkan ke
Dim xs() As Integer = ...
Dim ys() As Integer = ...
Dim zs = _
xs.GroupJoin( _
ys, _
Function(x As Integer) x, _
Function(y As Integer) y, _
Function(x, group) New With {x, .g = group})...
Catatan.Group, Join, dan Into bukan kata yang dipesan.
Ekspresi Bersyarat
Ekspresi bersyarah If menguji ekspresi dan mengembalikan nilai.
ConditionalExpression
: 'If' OpenParenthesis BooleanExpression Comma Expression Comma Expression CloseParenthesis
| 'If' OpenParenthesis Expression Comma Expression CloseParenthesis
;
IIF Namun, tidak seperti fungsi runtime, ekspresi kondisional hanya mengevaluasi operand-nya jika perlu. Jadi, misalnya, ekspresi If(c Is Nothing, c.Name, "Unknown") tidak akan melemparkan pengecualian jika nilainya c adalah Nothing. Ekspresi bersyukur memiliki dua bentuk: satu yang mengambil dua operan dan satu yang mengambil tiga operand.
Jika tiga operand disediakan, ketiga ekspresi harus diklasifikasikan sebagai nilai, dan operand pertama harus berupa ekspresi Boolean. Jika hasilnya adalah ekspresi benar, maka ekspresi kedua akan menjadi hasil operator, jika tidak, ekspresi ketiga akan menjadi hasil operator. Jenis hasil ekspresi adalah jenis dominan antara jenis ekspresi kedua dan ketiga. Jika tidak ada jenis dominan, maka terjadi kesalahan waktu kompilasi.
Jika dua operand disediakan, kedua operand harus diklasifikasikan sebagai nilai, dan operand pertama harus berupa jenis referensi atau jenis nilai nullable. Ekspresi If(x, y) kemudian dievaluasi seolah-olah adalah ekspresi If(x IsNot Nothing, x, y), dengan dua pengecualian. Pertama, ekspresi pertama hanya pernah dievaluasi sekali, dan kedua, jika jenis operand kedua adalah jenis nilai yang tidak dapat diubah ke null dan jenis operand pertama adalah, ? dihapus dari jenis operand pertama saat menentukan jenis dominan untuk jenis hasil ekspresi. Contohnya:
Module Test
Sub Main()
Dim x?, y As Integer
Dim a?, b As Long
a = If(x, a) ' Result type: Long?
y = If(x, 0) ' Result type: Integer
End Sub
End Module
Dalam kedua bentuk ekspresi, jika operand adalah Nothing, jenisnya tidak digunakan untuk menentukan jenis dominan. Dalam kasus ekspresi If(<expression>, Nothing, Nothing), jenis dominan dianggap Objectsebagai .
Ekspresi Literal XML
Ekspresi literal XML mewakili nilai XML (eXtensible Markup Language) 1.0.
XMLLiteralExpression
: XMLDocument
| XMLElement
| XMLProcessingInstruction
| XMLComment
| XMLCDATASection
;
Hasil ekspresi literal XML adalah nilai yang ditik sebagai salah satu jenis dari System.Xml.Linq namespace. Jika jenis di namespace layanan tersebut tidak tersedia, ekspresi literal XML akan menyebabkan kesalahan waktu kompilasi. Nilai dihasilkan melalui panggilan konstruktor yang diterjemahkan dari ekspresi literal XML. Misalnya, kode:
Dim book As System.Xml.Linq.XElement = _
<book title="My book"></book>
kira-kira setara dengan kode:
Dim book As System.Xml.Linq.XElement = _
New System.Xml.Linq.XElement( _
"book", _
New System.Xml.Linq.XAttribute("title", "My book"))
Ekspresi literal XML dapat mengambil bentuk dokumen XML, elemen XML, instruksi pemrosesan XML, komentar XML, atau bagian CDATA.
Nota. Spesifikasi ini hanya berisi cukup deskripsi XML untuk menjelaskan perilaku bahasa Visual Basic. Informasi selengkapnya tentang XML dapat ditemukan di http://www.w3.org/TR/REC-xml/.
Aturan leksikal
XMLCharacter
: '<Unicode tab character (0x0009)>'
| '<Unicode linefeed character (0x000A)>'
| '<Unicode carriage return character (0x000D)>'
| '<Unicode characters 0x0020 - 0xD7FF>'
| '<Unicode characters 0xE000 - 0xFFFD>'
| '<Unicode characters 0x10000 - 0x10FFFF>'
;
XMLString
: XMLCharacter+
;
XMLWhitespace
: XMLWhitespaceCharacter+
;
XMLWhitespaceCharacter
: '<Unicode carriage return character (0x000D)>'
| '<Unicode linefeed character (0x000A)>'
| '<Unicode space character (0x0020)>'
| '<Unicode tab character (0x0009)>'
;
XMLNameCharacter
: XMLLetter
| XMLDigit
| '.'
| '-'
| '_'
| ':'
| XMLCombiningCharacter
| XMLExtender
;
XMLNameStartCharacter
: XMLLetter
| '_'
| ':'
;
XMLName
: XMLNameStartCharacter XMLNameCharacter*
;
XMLLetter
: '<Unicode character as defined in the Letter production of the XML 1.0 specification>'
;
XMLDigit
: '<Unicode character as defined in the Digit production of the XML 1.0 specification>'
;
XMLCombiningCharacter
: '<Unicode character as defined in the CombiningChar production of the XML 1.0 specification>'
;
XMLExtender
: '<Unicode character as defined in the Extender production of the XML 1.0 specification>'
;
Ekspresi literal XML ditafsirkan menggunakan aturan leksikal XML alih-alih aturan leksikal kode Visual Basic reguler. Dua set aturan umumnya berbeda dengan cara berikut:
Spasi kosong signifikan dalam XML. Akibatnya, tata bahasa untuk ekspresi literal XML secara eksplisit menyatakan di mana ruang kosong diizinkan. Spasi kosong tidak dipertahankan, kecuali ketika terjadi dalam konteks data karakter dalam elemen. Contohnya:
' The following element preserves no whitespace Dim e1 = _ <customer> <name>Bob</> </> ' The following element preserves all of the whitespace Dim e2 = _ <customer> Bob </>Spasi kosong ujung baris XML dinormalisasi sesuai dengan spesifikasi XML.
XML peka huruf besar/kecil. Kata kunci harus sama persis dengan casing, atau kesalahan waktu kompilasi akan terjadi.
Terminator garis dianggap sebagai spasi kosong di XML. Akibatnya, tidak ada karakter kelanjutan baris yang diperlukan dalam ekspresi literal XML.
XML tidak menerima karakter lebar penuh. Jika karakter lebar penuh digunakan, kesalahan waktu kompilasi akan terjadi.
Ekspresi yang disematkan
Ekspresi literal XML dapat berisi ekspresi yang disematkan. Ekspresi yang disematkan adalah ekspresi Visual Basic yang dievaluasi dan digunakan untuk mengisi satu atau beberapa nilai di lokasi ekspresi yang disematkan.
XMLEmbeddedExpression
: '<' '%' '=' LineTerminator? Expression LineTerminator? '%' '>'
;
Misalnya, kode berikut menempatkan string John Smith sebagai nilai elemen XML:
Dim name as String = "John Smith"
Dim element As System.Xml.Linq.XElement = <customer><%= name %></customer>
Ekspresi dapat disematkan dalam sejumlah konteks. Misalnya, kode berikut menghasilkan elemen bernama customer:
Dim name As String = "customer"
Dim element As System.Xml.Linq.XElement = <<%= name %>>John Smith</>
Setiap konteks di mana ekspresi yang disematkan dapat digunakan menentukan jenis yang akan diterima. Ketika dalam konteks bagian ekspresi dari ekspresi yang disematkan, aturan leksikal normal untuk kode Visual Basic masih berlaku, misalnya, kelanjutan baris harus digunakan:
' Visual Basic expression uses line continuation, XML does not
Dim element As System.Xml.Linq.XElement = _
<<%= name & _
name %>>John
Smith</>
Dokumen XML
XMLDocument
: XMLDocumentPrologue XMLMisc* XMLDocumentBody XMLMisc*
;
XMLDocumentPrologue
: '<' '?' 'xml' XMLVersion XMLEncoding? XMLStandalone? XMLWhitespace? '?' '>'
;
XMLVersion
: XMLWhitespace 'version' XMLWhitespace? '=' XMLWhitespace? XMLVersionNumberValue
;
XMLVersionNumberValue
: SingleQuoteCharacter '1' '.' '0' SingleQuoteCharacter
| DoubleQuoteCharacter '1' '.' '0' DoubleQuoteCharacter
;
XMLEncoding
: XMLWhitespace 'encoding' XMLWhitespace? '=' XMLWhitespace? XMLEncodingNameValue
;
XMLEncodingNameValue
: SingleQuoteCharacter XMLEncodingName SingleQuoteCharacter
| DoubleQuoteCharacter XMLEncodingName DoubleQuoteCharacter
;
XMLEncodingName
: XMLLatinAlphaCharacter XMLEncodingNameCharacter*
;
XMLEncodingNameCharacter
: XMLUnderscoreCharacter
| XMLLatinAlphaCharacter
| XMLNumericCharacter
| XMLPeriodCharacter
| XMLDashCharacter
;
XMLLatinAlphaCharacter
: '<Unicode Latin alphabetic character (0x0041-0x005a, 0x0061-0x007a)>'
;
XMLNumericCharacter
: '<Unicode digit character (0x0030-0x0039)>'
;
XMLHexNumericCharacter
: XMLNumericCharacter
| '<Unicode Latin hex alphabetic character (0x0041-0x0046, 0x0061-0x0066)>'
;
XMLPeriodCharacter
: '<Unicode period character (0x002e)>'
;
XMLUnderscoreCharacter
: '<Unicode underscore character (0x005f)>'
;
XMLDashCharacter
: '<Unicode dash character (0x002d)>'
;
XMLStandalone
: XMLWhitespace 'standalone' XMLWhitespace? '=' XMLWhitespace? XMLYesNoValue
;
XMLYesNoValue
: SingleQuoteCharacter XMLYesNo SingleQuoteCharacter
| DoubleQuoteCharacter XMLYesNo DoubleQuoteCharacter
;
XMLYesNo
: 'yes'
| 'no'
;
XMLMisc
: XMLComment
| XMLProcessingInstruction
| XMLWhitespace
;
XMLDocumentBody
: XMLElement
| XMLEmbeddedExpression
;
Dokumen XML menghasilkan nilai yang ditik sebagai System.Xml.Linq.XDocument. Tidak seperti spesifikasi XML 1.0, dokumen XML dalam ekspresi literal XML diperlukan untuk menentukan prolog dokumen XML; Ekspresi literal XML tanpa prolog dokumen XML ditafsirkan sebagai entitas individual mereka. Contohnya:
Dim doc As System.Xml.Linq.XDocument = _
<?xml version="1.0"?>
<?instruction?>
<customer>Bob</>
Dim pi As System.Xml.Linq.XProcessingInstruction = _
<?instruction?>
Dokumen XML dapat berisi ekspresi tersemat yang jenisnya bisa apa saja; namun, pada runtime, objek harus memenuhi persyaratan XDocument konstruktor atau kesalahan run-time akan terjadi.
Tidak seperti XML biasa, ekspresi dokumen XML tidak mendukung DTD (Deklarasi Tipe Dokumen). Selain itu, atribut pengodean, jika disediakan, akan diabaikan karena pengodean ekspresi literal Xml selalu sama dengan pengodean file sumber itu sendiri.
Nota. Meskipun atribut pengodean diabaikan, atribut ini masih valid untuk mempertahankan kemampuan untuk menyertakan dokumen Xml 1.0 yang valid dalam kode sumber.
Elemen XML
XMLElement
: XMLEmptyElement
| XMLElementStart XMLContent XMLElementEnd
;
XMLEmptyElement
: '<' XMLQualifiedNameOrExpression XMLAttribute* XMLWhitespace? '/' '>'
;
XMLElementStart
: '<' XMLQualifiedNameOrExpression XMLAttribute* XMLWhitespace? '>'
;
XMLElementEnd
: '<' '/' '>'
| '<' '/' XMLQualifiedName XMLWhitespace? '>'
;
XMLContent
: XMLCharacterData? ( XMLNestedContent XMLCharacterData? )+
;
XMLCharacterData
: '<Any XMLCharacterDataString that does not contain the string "]]>">'
;
XMLCharacterDataString
: '<Any Unicode character except < or &>'+
;
XMLNestedContent
: XMLElement
| XMLReference
| XMLCDATASection
| XMLProcessingInstruction
| XMLComment
| XMLEmbeddedExpression
;
XMLAttribute
: XMLWhitespace XMLAttributeName XMLWhitespace? '=' XMLWhitespace? XMLAttributeValue
| XMLWhitespace XMLEmbeddedExpression
;
XMLAttributeName
: XMLQualifiedNameOrExpression
| XMLNamespaceAttributeName
;
XMLAttributeValue
: DoubleQuoteCharacter XMLAttributeDoubleQuoteValueCharacter* DoubleQuoteCharacter
| SingleQuoteCharacter XMLAttributeSingleQuoteValueCharacter* SingleQuoteCharacter
| XMLEmbeddedExpression
;
XMLAttributeDoubleQuoteValueCharacter
: '<Any XMLCharacter except <, &, or DoubleQuoteCharacter>'
| XMLReference
;
XMLAttributeSingleQuoteValueCharacter
: '<Any XMLCharacter except <, &, or SingleQuoteCharacter>'
| XMLReference
;
XMLReference
: XMLEntityReference
| XMLCharacterReference
;
XMLEntityReference
: '&' XMLEntityName ';'
;
XMLEntityName
: 'lt' | 'gt' | 'amp' | 'apos' | 'quot'
;
XMLCharacterReference
: '&' '#' XMLNumericCharacter+ ';'
| '&' '#' 'x' XMLHexNumericCharacter+ ';'
;
Elemen XML menghasilkan nilai yang dititik sebagai System.Xml.Linq.XElement. Tidak seperti XML biasa, elemen XML dapat menghilangkan nama dalam tag penutup dan elemen yang paling berlapis saat ini akan ditutup. Contohnya:
Dim name = <name>Bob</>
Deklarasi atribut dalam elemen XML menghasilkan nilai yang diketik sebagai System.Xml.Linq.XAttribute. Nilai atribut dinormalisasi sesuai dengan spesifikasi XML. Ketika nilai atribut adalah Nothing atribut tidak akan dibuat, sehingga ekspresi nilai atribut tidak perlu diperiksa untuk Nothing. Contohnya:
Dim expr = Nothing
' Throws null argument exception
Dim direct = New System.Xml.Linq.XElement( _
"Name", _
New System.Xml.Linq.XAttribute("Length", expr))
' Doesn't throw exception, the result is <Name/>
Dim literal = <Name Length=<%= expr %>/>
Elemen dan atribut XML dapat berisi ekspresi berlapis di tempat-tempat berikut:
Nama elemen, dalam hal ini ekspresi yang disematkan harus merupakan nilai dari jenis yang secara implisit dapat dikonversi ke System.Xml.Linq.XName. Contohnya:
Dim name = <<%= "name" %>>Bob</>
Nama atribut elemen, dalam hal ini ekspresi yang disematkan harus merupakan nilai dari jenis yang secara implisit dapat dikonversi ke System.Xml.Linq.XName. Contohnya:
Dim name = <name <%= "length" %>="3">Bob</>
Nilai atribut elemen , dalam hal ini ekspresi yang disematkan dapat menjadi nilai dari jenis apa pun. Contohnya:
Dim name = <name length=<%= 3 %>>Bob</>
Atribut elemen , dalam hal ini ekspresi yang disematkan dapat menjadi nilai dari jenis apa pun. Contohnya:
Dim name = <name <%= new XAttribute("length", 3) %>>Bob</>
Konten elemen , dalam hal ini ekspresi yang disematkan dapat menjadi nilai dari jenis apa pun. Contohnya:
Dim name = <name><%= "Bob" %></>
Jika jenis ekspresi yang disematkan adalah Object(), array akan diteruskan sebagai paramarray ke XElement konstruktor.
Ruang Nama XML
Elemen XML dapat berisi deklarasi namespace XML, seperti yang ditentukan oleh spesifikasi namespace XML 1.0.
XMLNamespaceAttributeName
: XMLPrefixedNamespaceAttributeName
| XMLDefaultNamespaceAttributeName
;
XMLPrefixedNamespaceAttributeName
: 'xmlns' ':' XMLNamespaceName
;
XMLDefaultNamespaceAttributeName
: 'xmlns'
;
XMLNamespaceName
: XMLNamespaceNameStartCharacter XMLNamespaceNameCharacter*
;
XMLNamespaceNameStartCharacter
: '<Any XMLNameCharacter except :>'
;
XMLNamespaceNameCharacter
: XMLLetter
| '_'
;
XMLQualifiedNameOrExpression
: XMLQualifiedName
| XMLEmbeddedExpression
;
XMLQualifiedName
: XMLPrefixedName
| XMLUnprefixedName
;
XMLPrefixedName
: XMLNamespaceName ':' XMLNamespaceName
;
XMLUnprefixedName
: XMLNamespaceName
;
Pembatasan menentukan namespace xml layanan dan xmlns diberlakukan dan akan menghasilkan kesalahan waktu kompilasi. Deklarasi namespace XML tidak boleh memiliki ekspresi yang disematkan untuk nilainya; nilai yang disediakan harus berupa string literal yang tidak kosong. Contohnya:
' Declares a valid namespace
Dim customer = <db:customer xmlns:db="http://example.org/database">Bob</>
' Error: xmlns cannot be re-defined
Dim bad1 = <elem xmlns:xmlns="http://example.org/namespace"/>
' Error: cannot have an embedded expression
Dim bad2 = <elem xmlns:db=<%= "http://example.org/database" %>>Bob</>
Nota. Spesifikasi ini hanya berisi cukup deskripsi namespace XML untuk menjelaskan perilaku bahasa Visual Basic. Informasi selengkapnya tentang namespace XML dapat ditemukan di http://www.w3.org/TR/REC-xml-names/.
Elemen XML dan nama atribut dapat memenuhi syarat menggunakan nama namespace layanan. Namespace terikat seperti dalam XML reguler, dengan pengecualian bahwa setiap impor namespace yang dideklarasikan pada tingkat file dianggap dideklarasikan dalam konteks yang mencakup deklarasi, yang dengan sendirinya diapit oleh impor namespace apa pun yang dideklarasikan oleh lingkungan kompilasi. Jika nama namespace tidak dapat ditemukan, kesalahan waktu kompilasi terjadi. Contohnya:
Imports System.Xml.Linq
Imports <xmlns:db="http://example.org/database">
Module Test
Sub Main()
' Binds to the imported namespace above.
Dim c1 = <db:customer>Bob</>
' Binds to the namespace declaration in the element
Dim c2 = _
<db:customer xmlns:db="http://example.org/database-other">Mary</>
' Binds to the inner namespace declaration
Dim c3 = _
<database xmlns:db="http://example.org/database-one">
<db:customer xmlns:db="http://example.org/database-two">Joe</>
</>
' Error: namespace db2 cannot be found
Dim c4 = _
<db2:customer>Jim</>
End Sub
End Module
Namespace XML yang dideklarasikan dalam elemen tidak berlaku untuk literal XML di dalam ekspresi yang disematkan. Contohnya:
' Error: Namespace prefix 'db' is not declared
Dim customer = _
<db:customer xmlns:db="http://example.org/database">
<%= <db:customer>Bob</> %>
</>
Nota. Ini karena ekspresi yang disematkan bisa apa saja, termasuk panggilan fungsi. Jika panggilan fungsi berisi ekspresi literal XML, tidak jelas apakah programmer akan mengharapkan namespace XML diterapkan atau diabaikan.
Instruksi Pemrosesan XML
Instruksi pemrosesan XML menghasilkan nilai yang dititik sebagai System.Xml.Linq.XProcessingInstruction. Instruksi pemrosesan XML tidak boleh berisi ekspresi yang disematkan, karena merupakan sintaks yang valid dalam instruksi pemrosesan.
XMLProcessingInstruction
: '<' '?' XMLProcessingTarget ( XMLWhitespace XMLProcessingValue? )? '?' '>'
;
XMLProcessingTarget
: '<Any XMLName except a casing permutation of the string "xml">'
;
XMLProcessingValue
: '<Any XMLString that does not contain a question-mark followed by ">">'
;
Komentar XML
Komentar XML menghasilkan nilai yang ditik sebagai System.Xml.Linq.XComment. Komentar XML tidak boleh berisi ekspresi yang disematkan, karena merupakan sintaks yang valid dalam komentar.
XMLComment
: '<' '!' '-' '-' XMLCommentCharacter* '-' '-' '>'
;
XMLCommentCharacter
: '<Any XMLCharacter except dash (0x002D)>'
| '-' '<Any XMLCharacter except dash (0x002D)>'
;
Bagian CDATA
Bagian CDATA menghasilkan nilai yang ditik sebagai System.Xml.Linq.XCData. Bagian CDATA tidak boleh berisi ekspresi yang disematkan, karena merupakan sintaks yang valid dalam bagian CDATA.
XMLCDATASection
: '<' '!' ( 'CDATA' '[' XMLCDATASectionString? ']' )? '>'
;
XMLCDATASectionString
: '<Any XMLString that does not contain the string "]]>">'
;
Ekspresi Akses Anggota XML
Ekspresi akses anggota XML mengakses anggota nilai XML.
XMLMemberAccessExpression
: Expression '.' LineTerminator? '<' XMLQualifiedName '>'
| Expression '.' LineTerminator? '@' LineTerminator? '<' XMLQualifiedName '>'
| Expression '.' LineTerminator? '@' LineTerminator? IdentifierOrKeyword
| Expression '.' '.' '.' LineTerminator? '<' XMLQualifiedName '>'
;
Ada tiga jenis ekspresi akses anggota XML:
Akses elemen, di mana nama XML mengikuti satu titik. Contohnya:
Dim customer = _ <customer> <name>Bob</> </> Dim customerName = customer.<name>.ValuePeta akses elemen ke fungsi:
Function Elements(name As System.Xml.Linq.XName) As _ System.Collections.Generic.IEnumerable(Of _ System.Xml.Linq.XNode)Jadi contoh di atas setara dengan:
Dim customerName = customer.Elements("name").ValueAkses atribut, di mana pengidentifikasi Visual Basic mengikuti titik dan tanda, atau nama XML mengikuti titik dan tanda tangan. Contohnya:
Dim customer = <customer age="30"/> Dim customerAge = customer.@agePeta akses atribut ke fungsi:
Function AttributeValue(name As System.Xml.Linq.XName) as StringJadi contoh di atas setara dengan:
Dim customerAge = customer.AttributeValue("age")Nota. Metode
AttributeValueekstensi (serta propertiValueekstensi terkait ) saat ini tidak didefinisikan dalam rakitan apa pun. Jika anggota ekstensi diperlukan, mereka secara otomatis didefinisikan dalam perakitan yang sedang diproduksi.Akses descendents, di mana nama XML mengikuti tiga titik. Contohnya:
Dim company = _ <company> <customers> <customer>Bob</> <customer>Mary</> <customer>Joe</> </> </> Dim customers = company...<customer>Descendents mengakses peta ke fungsi:
Function Descendents(name As System.Xml.Linq.XName) As _ System.Collections.Generic.IEnumerable(Of _ System.Xml.Linq.XElement)Jadi contoh di atas setara dengan:
Dim customers = company.Descendants("customer")
Ekspresi dasar ekspresi akses anggota XML harus berupa nilai dan harus berjenis:
Jika elemen atau turunan mengakses,
System.Xml.Linq.XContaineratau jenis turunan, atauSystem.Collections.Generic.IEnumerable(Of T)atau jenis turunan, di manaTadalahSystem.Xml.Linq.XContaineratau jenis turunan.Jika akses atribut,
System.Xml.Linq.XElementatau jenis turunan, atauSystem.Collections.Generic.IEnumerable(Of T)jenis turunan, di manaTadalahSystem.Xml.Linq.XElementatau jenis turunan.
Nama dalam ekspresi akses anggota XML tidak boleh kosong. Mereka dapat memenuhi syarat namespace layanan, menggunakan namespace apa pun yang ditentukan oleh impor. Contohnya:
Imports <xmlns:db="http://example.org/database">
Module Test
Sub Main()
Dim customer = _
<db:customer>
<db:name>Bob</>
</>
Dim name = customer.<db:name>
End Sub
End Module
Spasi kosong tidak diperbolehkan setelah titik dalam ekspresi akses anggota XML, atau antara tanda kurung sudut dan nama. Contohnya:
Dim customer = _
<customer age="30">
<name>Bob</>
</>
' All the following are error cases
Dim age = customer.@ age
Dim name = customer.< name >
Dim names = customer...< name >
Jika jenis di System.Xml.Linq namespace tidak tersedia, ekspresi akses anggota XML akan menyebabkan kesalahan waktu kompilasi.
Operator Tunggu
Operator tunggu terkait dengan metode asinkron, yang dijelaskan dalam Metode Asinkron Bagian.
AwaitOperatorExpression
: 'Await' Expression
;
Await adalah kata yang dicadangkan jika metode penutup segera atau ekspresi lambda di mana ia muncul memiliki Async pengubah, dan jika Await muncul setelah Async pengubah tersebut; itu tidak dilayani di tempat lain. Ini juga tidak dilayani dalam direktif praproscessor. Operator tunggu hanya diizinkan dalam isi metode atau ekspresi lambda di mana itu adalah kata yang dipesan. Dalam metode penutup segera atau lambda, ekspresi tunggu mungkin tidak terjadi di dalam isi Catch blok, Finally atau di dalam isi SyncLock pernyataan, atau di dalam ekspresi kueri.
Operator tunggu mengambil ekspresi tunggal yang harus diklasifikasikan sebagai nilai dan yang jenisnya harus merupakan jenis yang dapat ditunggu , atau Object. Jika jenisnya, Object maka semua pemrosesan ditangguhkan hingga run-time. Jenis C dikatakan dapat ditunggu jika semua hal berikut ini benar:
Cberisi instans yang dapat diakses atau metode ekstensi bernamaGetAwaiteryang tidak memiliki argumen dan yang mengembalikan beberapa jenisE;Eberisi instans atau properti ekstensi yang dapat dibaca bernamaIsCompletedyang tidak mengambil argumen dan memiliki jenis Boolean;Eberisi instans atau metode ekstensi yang dapat diakses bernamaGetResultyang tidak mengambil argumen;Emengimplementasikan atauSystem.Runtime.CompilerServices.INotifyCompletionICriticalNotifyCompletion.
Jika GetResult adalah Sub, maka ekspresi tunggu diklasifikasikan sebagai batal. Jika tidak, ekspresi tunggu diklasifikasikan sebagai nilai dan jenisnya adalah jenis GetResult pengembalian metode.
Berikut adalah contoh kelas yang dapat ditunggu:
Class MyTask(Of T)
Function GetAwaiter() As MyTaskAwaiter(Of T)
Return New MyTaskAwaiter With {.m_Task = Me}
End Function
...
End Class
Structure MyTaskAwaiter(Of T)
Implements INotifyCompletion
Friend m_Task As MyTask(Of T)
ReadOnly Property IsCompleted As Boolean
Get
Return m_Task.IsCompleted
End Get
End Property
Sub OnCompleted(r As Action) Implements INotifyCompletion.OnCompleted
' r is the "resumptionDelegate"
Dim sc = SynchronizationContext.Current
If sc Is Nothing Then
m_Task.ContinueWith(Sub() r())
Else
m_Task.ContinueWith(Sub() sc.Post(Sub() r(), Nothing))
End If
End Sub
Function GetResult() As T
If m_Task.IsCanceled Then Throw New TaskCanceledException(m_Task)
If m_Task.IsFaulted Then Throw m_Task.Exception.InnerException
Return m_Task.Result
End Function
End Structure
Nota. Penulis pustaka disarankan untuk mengikuti pola yang mereka panggil delegasi kelanjutan sama SynchronizationContext seperti OnCompleted yang dipanggil sendiri. Selain itu, delegasi penerbitan ulang tidak boleh dijalankan secara sinkron dalam OnCompleted metode karena dapat menyebabkan luapan tumpukan: sebagai gantinya, delegasi harus diantrekan untuk eksekusi berikutnya.
Saat alur kontrol mencapai Await operator, perilaku adalah sebagai berikut.
Metode
GetAwaiteroperand yang ditunggu dipanggil. Hasil dari pemanggilan ini disebut awaiter.Properti awaiter
IsCompleteddiambil. Jika hasilnya benar maka:- Metode
GetResultawaiter dipanggil. JikaGetResultadalah fungsi, maka nilai ekspresi tunggu adalah nilai kembali dari fungsi ini.
- Metode
Jika properti IsCompleted tidak benar, maka:
Baik
ICriticalNotifyCompletion.UnsafeOnCompleteddipanggil pada awaiter (jika jenisEawaiter mengimplementasikanICriticalNotifyCompletion) atauINotifyCompletion.OnCompleted(sebaliknya). Dalam kedua kasus, ia melewati delegasi penerbitan ulang yang terkait dengan instans metode asinkron saat ini.Titik kontrol instans metode asinkron saat ini ditangguhkan, dan alur kontrol dilanjutkan di pemanggil saat ini (ditentukan dalam Metode Asinkron Bagian).
Jika nanti delegasi penerbitan ulang dipanggil,
- delegasi kembali mendelegasikan pemulihan
System.Threading.Thread.CurrentThread.ExecutionContextpertama ke apa yang pada saatOnCompleteditu dipanggil, - kemudian melanjutkan alur kontrol di titik kontrol instans metode asinkron (lihat Bagian Metode Asinkron),
- di mana ia memanggil
GetResultmetode awaiter, seperti pada 2.1 di atas.
- delegasi kembali mendelegasikan pemulihan
Jika operand yang ditunggu memiliki tipe Objek, maka perilaku ini ditangguhkan hingga runtime:
- Langkah 1 dicapai dengan memanggil GetAwaiter() tanpa argumen; oleh karena itu dapat mengikat pada runtime ke metode instans yang mengambil parameter opsional.
- Langkah 2 dicapai dengan mengambil properti IsCompleted() tanpa argumen, dan dengan mencoba konversi intrinsik ke Boolean.
- Langkah 3.a dicapai dengan mencoba
TryCast(awaiter, ICriticalNotifyCompletion), dan jika ini gagal makaDirectCast(awaiter, INotifyCompletion).
Delegasi penerbitan ulang yang diteruskan dalam 3.a hanya dapat dipanggil sekali. Jika dipanggil lebih dari sekali, perilaku tersebut tidak ditentukan.
Visual Basic language spec