Di VB.NET ini terjadi:
Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing
y = 5
If x <> y Then
Console.WriteLine("true")
Else
Console.WriteLine("false") '' <-- I got this. Why?
End If
Tetapi di C # ini terjadi:
decimal? x = default(decimal?);
decimal? y = default(decimal?);
y = 5;
if (x != y)
{
Debug.WriteLine("true"); // <-- I got this -- I'm with you, C# :)
}
else
{
Debug.WriteLine("false");
}
Mengapa ada perbedaan?
default(decimal?)
mengembalikan 0, bukannull
.null
If
conditional tidak perlu dievaluasi sebagai boolean … uuuugh EDIT: JadiNothing <> Anything = Nothing
yang berakibat padaIf
pengambilan negative / else route.Jawaban:
VB.NET dan C # .NET adalah bahasa yang berbeda, dibuat oleh tim berbeda yang membuat asumsi berbeda tentang penggunaan; dalam hal ini semantik perbandingan NULL.
Preferensi pribadi saya adalah untuk semantik VB.NET, yang pada dasarnya memberi NULL semantik "Saya belum tahu". Kemudian perbandingan 5 dengan "Saya belum tahu". secara alami adalah "Saya belum tahu"; yaitu NULL. Ini memiliki keuntungan tambahan untuk mencerminkan perilaku NULL di (sebagian besar jika tidak semua) database SQL. Ini juga merupakan interpretasi yang lebih standar (daripada C #) dari logika tiga nilai, seperti yang dijelaskan di sini .
Tim C # membuat asumsi berbeda tentang arti NULL, yang mengakibatkan perbedaan perilaku yang Anda tunjukkan. Eric Lippert menulis blog tentang arti NULL dalam C # . Menurut Eric Lippert: "Saya juga menulis tentang semantik nulls di VB / VBScript dan JScript di sini dan di sini ".
Dalam lingkungan apa pun di mana nilai NULL dimungkinkan, penting untuk mengakui bahwa Law of the Excluded Middle (yaitu bahwa A atau ~ A secara tautologis benar) tidak lagi dapat diandalkan.
Memperbarui:
A
bool
(sebagai lawan abool?
) hanya dapat mengambil nilai TRUE dan FALSE. Namun implementasi bahasa NULL harus memutuskan bagaimana NULL menyebar melalui ekspresi. Dalam VB ekspresi5=null
dan5<>null
KEDUA mengembalikan false. Di C #, dari ekspresi yang sebanding5==null
dan5!=null
hanya yangkeduapertama [diperbarui 2014-03-02 - PG] mengembalikan false. Namun, di SETIAP lingkungan yang mendukung null, adalah kewajiban programmer untuk mengetahui tabel kebenaran dan propagasi null yang digunakan oleh bahasa tersebut.Memperbarui
Artikel blog Eric Lippert (disebutkan dalam komentarnya di bawah) tentang semantik sekarang ada di:
30 September 2003 - A Whole Lot of Nothing
1 Oktober 2003 - A Little More on Nothing
sumber
bool
tidak boleh memiliki 3 nilai, hanya dua. Itubool?
bisa memiliki tiga nilai.operator ==
danoperator !=
keduanya kembalibool
, tidakbool?
, terlepas dari jenis operannya. Selain itu,if
pernyataan hanya dapat menerima abool
, bukanbool?
.5=null
dan5<>null
tidak valid. Dan dari5 == null
dan5 != null
, apakah Anda yakin ini adalah detik yang kembalifalse
?Karena
x <> y
kembali,Nothing
bukantrue
. Itu tidak didefinisikan karenax
tidak didefinisikan. (mirip dengan SQL null).Catatan: VB.NET
Nothing
<> C #null
.Anda juga harus membandingkan nilai a
Nullable(Of Decimal)
hanya jika memiliki nilai.Jadi VB.NET di atas mirip dengan ini (yang terlihat kurang salah):
Spesifikasi bahasa VB.NET :
Sebagai contoh:
sumber
Lihatlah CIL yang dihasilkan (saya telah mengubah keduanya menjadi C #):
C #:
Dasar visual:
Anda akan melihat bahwa perbandingan dalam Visual Basic mengembalikan Nullable <bool> (bukan bool, false atau true!). Dan undefined dikonversi ke bool adalah false.
Nothing
dibandingkan dengan apa pun yang selaluNothing
, tidak salah dalam Visual Basic (sama seperti di SQL).sumber
Masalah yang diamati di sini adalah kasus khusus dari masalah yang lebih umum, yaitu jumlah definisi berbeda tentang persamaan yang mungkin berguna setidaknya dalam beberapa keadaan melebihi jumlah sarana yang umumnya tersedia untuk mengungkapkannya. Masalah ini dalam beberapa kasus diperburuk oleh keyakinan yang tidak menguntungkan bahwa membingungkan untuk memiliki cara berbeda untuk menguji kesetaraan menghasilkan hasil yang berbeda, dan kebingungan seperti itu dapat dihindari dengan memiliki bentuk persamaan yang berbeda menghasilkan hasil yang sama bila memungkinkan.
Pada kenyataannya, penyebab mendasar dari kebingungan adalah kepercayaan yang salah arah bahwa berbagai bentuk pengujian kesetaraan dan ketidaksetaraan diharapkan dapat memberikan hasil yang sama, terlepas dari kenyataan bahwa semantik yang berbeda berguna dalam keadaan yang berbeda. Misalnya, dari sudut pandang aritmatika, sangat berguna untuk dapat memiliki
Decimal
yang hanya berbeda dalam jumlah angka nol tertinggal yang dibandingkan sebagai sama. Begitu juga untukdouble
nilai seperti nol positif dan nol negatif. Di sisi lain, dari sudut pandang caching atau interning, semantik semacam itu bisa mematikan. Misalkan, misalnya, seseorang memiliki suatuDictionary<Decimal, String>
hal yangmyDict[someDecimal]
seharusnya samasomeDecimal.ToString()
. Objek seperti itu akan tampak masuk akal jika ada banyakDecimal
nilai yang ingin diubah menjadi string dan diharapkan ada banyak duplikat. Sayangnya, jika digunakan caching seperti itu untuk mengubah 12,3 m dan 12,40 m, diikuti oleh 12,30 m dan 12,4 m, nilai terakhir akan menghasilkan "12.3", dan "12.4", bukan "12.30" dan "12.4".Kembali ke masalah yang ada, ada lebih dari satu cara yang masuk akal untuk membandingkan objek nullable untuk persamaan. C # mengambil sudut pandang bahwa
==
operatornya harus mencerminkan perilakunyaEquals
. VB.NET mengambil sudut pandang bahwa perilakunya harus mencerminkan beberapa bahasa lain, karena siapa pun yang menginginkanEquals
perilakunya dapat menggunakanEquals
. Dalam beberapa hal, solusi yang tepat adalah memiliki konstruksi "jika" tiga arah, dan mengharuskan jika ekspresi kondisional mengembalikan hasil bernilai tiga, kode harus menentukan apa yang harus terjadi dinull
kasus tersebut. Karena itu bukan pilihan untuk bahasa apa adanya, alternatif terbaik berikutnya adalah mempelajari cara kerja bahasa yang berbeda dan mengenali bahwa keduanya tidak sama.Secara kebetulan, operator "Is" Visual Basic, yang kurang dalam C, dapat digunakan untuk menguji apakah objek nullable, sebenarnya, null. Meskipun orang mungkin secara wajar mempertanyakan apakah suatu
if
pengujian harus menerima aBoolean?
, meminta operator pembanding normal mengembalikanBoolean?
daripadaBoolean
saat dipanggil pada tipe nullable adalah fitur yang berguna. Kebetulan, di VB.NET, jika seseorang mencoba menggunakan operator persamaan daripadaIs
, ia akan mendapat peringatan bahwa hasil perbandingan akan selaluNothing
, dan seseorang harus menggunakanIs
jika ingin menguji apakah ada sesuatu yang nol.sumber
== null
. Dan menguji apakah tipe nilai nullable memiliki nilai dilakukan oleh.hasValue
. Apa gunanyaIs Nothing
operator? C # memang memilikiis
tetapi menguji kompatibilitas tipe. Sehubungan dengan ini, saya benar-benar tidak yakin apa yang coba dikatakan paragraf terakhir Anda.null
, meskipun kedua bahasa memperlakukannya sebagai gula sintaksis untukHasValue
pemeriksaan, setidaknya dalam kasus di mana jenisnya diketahui (saya tidak yakin kode apa yang dihasilkan untuk obat generik).Semoga postingan ini membantu Anda:
Jika saya ingat dengan benar, 'Nothing' dalam VB berarti "nilai default". Untuk tipe nilai, itulah nilai defaultnya, untuk tipe referensi, nilainya null. Jadi, tidak menugaskan apa pun ke struct, tidak masalah sama sekali.
sumber
<>
operator di VB, dan bagaimana operasinya pada tipe nullable.Ini adalah keanehan yang pasti dari VB.
Di VB, jika Anda ingin membandingkan dua tipe nullable, Anda harus menggunakan
Nullable.Equals()
.Dalam contoh Anda, seharusnya:
sumber
Nullable<>.Equals()
. Seseorang mungkin mengharapkannya untuk bekerja dengan cara yang sama (seperti yang dilakukan C #).Nullable
tidak ada di versi pertama .NET, itu dibuat setelah C # dan VB.NET telah keluar untuk beberapa waktu dan sudah menentukan perilaku propagasi null mereka. Apakah Anda benar-benar mengharapkan bahasa tersebut konsisten dengan jenis yang tidak akan dibuat selama beberapa tahun? Dari sudut pandang programmer VB.NET, ini adalah Nullable. Sama yang tidak konsisten dengan bahasanya, bukan sebaliknya. (Mengingat bahwa C # dan VB keduanya menggunakanNullable
definisi yang sama , tidak mungkin itu konsisten dengan kedua bahasa.)Kode VB Anda salah - jika Anda mengubah "x <> y" menjadi "x = y", Anda masih akan mendapatkan "false" sebagai hasilnya. Cara paling umum untuk mengungkapkan ini untuk instance nullable adalah "Not x.Equals (y)", dan ini akan menghasilkan perilaku yang sama seperti "x! = Y" di C #.
sumber
x
adalahnothing
, dalam halx.Equals(y)
akan melemparkan sebuah pengecualian.