Pertimbangkan kode ini:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Keduanya int
dan short
merupakan tipe primitif, tetapi perbandingan dengan ==
pengembalian benar dan perbandingan dengan Equals
pengembalian salah.
Mengapa?
Console.WriteLine(age.Equals(newAge));
Equals()
yang secara umum.Jawaban:
Jawaban singkat:
Kesetaraan itu rumit.
Jawaban terinci:
Tipe primitif menimpa basis
object.Equals(object)
dan mengembalikan true jika kotakobject
itu dari jenis dan nilai yang sama. (Perhatikan bahwa ini juga akan berfungsi untuk tipe yang dapat dibatalkan; tipe yang tidak dapat dibatalkan dapat selalu kotak ke instance dari tipe yang mendasarinya.)Karena
newAge
ashort
,Equals(object)
metodenya hanya mengembalikan true jika Anda melewatkan kotak pendek dengan nilai yang sama. Anda melewati kotakint
, jadi mengembalikan salah.Sebaliknya,
==
operator didefinisikan sebagai mengambil duaint
s (ataushort
s ataulong
s).Ketika Anda memanggilnya dengan a
int
dan ashort
, kompiler akan secara implisit mengonversikanshort
keint
dan membandingkan hasilint
dengan nilai.Cara lain untuk membuatnya bekerja
Tipe primitif juga memiliki
Equals()
metode mereka sendiri yang menerima tipe yang sama.Jika Anda menulis
age.Equals(newAge)
, kompiler akan memilihint.Equals(int)
sebagai kelebihan beban terbaik dan secara implisit dikonversishort
keint
. Kemudian akan kembalitrue
, karena metode ini hanya membandingkanint
s secara langsung.short
juga memilikishort.Equals(short)
metode, tetapiint
tidak dapat secara implisit dikonversishort
, jadi Anda tidak memanggilnya.Anda bisa memaksanya untuk memanggil metode ini dengan gips:
Ini akan menelepon
short.Equals(short)
langsung, tanpa tinju. Jikaage
lebih besar dari 32767, itu akan membuang pengecualian melimpah.Anda juga bisa memanggil
short.Equals(object)
kelebihan, tetapi secara eksplisit melewati objek kotak sehingga mendapat jenis yang sama:Seperti alternatif sebelumnya, ini akan membuang kelebihan jika tidak sesuai
short
. Berbeda dengan solusi sebelumnya, ia akan mengotakkanshort
objek, membuang-buang waktu dan memori.Kode sumber:
Berikut adalah kedua
Equals()
metode dari kode sumber aktual:Bacaan lebih lanjut:
Lihat Eric Lippert .
sumber
long == int
,int
secara implisit dikonversi kelong
kanan?int age = 25;
untukconst int age = 25;
, maka hasilnya akan berubah. Itu karena konversi implisit dariint
keshort
memang ada dalam kasus itu. Lihat Konversi ekspresi konstan implisit .==
Operator membandingkan jenis referensi dengan referensi. Untuk tipe nilai, dan untuk tipe yang kelebihan beban==
, tidak.Karena tidak ada kelebihan untuk
short.Equals
yang menerimaint
. Oleh karena itu, ini disebut:obj
bukanshort
.. karena itu, itu salah.sumber
Ketika Anda lulus
int
keshort
Sama Anda lulusobject
:Jadi pseudocode ini berjalan:
sumber
Untuk tipe nilai,
.Equals
mengharuskan kedua objek memiliki tipe yang sama dan memiliki nilai yang sama, sementara==
hanya menguji apakah kedua nilai tersebut sama.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
sumber
==
digunakan untuk memeriksa kondisi yang sama, dapat dianggap sebagai operator (operator boolean), hanya untuk membandingkan 2 hal dan di sini tipe data tidak masalah karena akan ada tipe casting yang dilakukan danEquals
juga digunakan untuk memeriksa kondisi yang sama , tetapi dalam hal ini tipe data harus sama. N Equals adalah metode bukan operator.Di bawah ini adalah contoh kecil yang diambil dari yang Anda berikan dan ini akan menjelaskan perbedaan secara singkat ,.
dalam contoh di atas, X dan Y memiliki nilai yang sama yaitu 1, dan ketika kita menggunakan
==
, itu akan mengembalikan true, seperti dalam kasus==
, tipe pendek dikonversi menjadi int oleh kompiler dan hasilnya diberikan.dan ketika kita gunakan
Equals
, pembandingannya dilakukan, tetapi pengecoran tipe tidak dilakukan oleh kompiler, jadi false dikembalikan.Kawan, tolong beri tahu saya jika saya salah.
sumber
Dalam banyak konteks di mana metode atau argumen operator bukan dari tipe yang diperlukan, kompiler C # akan berusaha untuk melakukan konversi tipe implisit. Jika kompiler dapat membuat semua argumen memuaskan operator dan metode mereka dengan menambahkan konversi implisit, ia akan melakukannya tanpa keluhan, meskipun dalam beberapa kasus (terutama dengan tes kesetaraan!) Hasilnya mungkin mengejutkan.
Selanjutnya, setiap tipe nilai seperti
int
ataushort
benar - benar menggambarkan baik jenis nilai maupun jenis objek (*). Konversi tersirat ada untuk mengkonversi nilai ke jenis nilai lainnya, dan untuk mengkonversi segala jenis nilai ke jenis objek yang sesuai, tetapi berbagai jenis objek tidak secara implisit dapat dikonversi satu sama lain.Jika seseorang menggunakan
==
operator untuk membandingkan ashort
dan aint
, makashort
akan secara implisit dikonversi menjadiint
. Jika nilai numeriknya sama dengan nilaiint
,int
yang dikonversi akan samaint
dengan yang dibandingkan. Jika seseorang mencoba menggunakanEquals
metode ini untuk membandingkannya denganint
, bagaimanapun, satu-satunya konversi implisit yang akan memenuhi kelebihanEquals
metode adalah konversi ke jenis objek yang sesuai denganint
. Ketikashort
ditanya apakah cocok dengan objek yang lewat, ia akan mengamati bahwa objek tersebut adalahint
bukan daripadashort
dan dengan demikian menyimpulkan bahwa itu tidak mungkin sama.Secara umum, meskipun kompiler tidak akan mengeluh tentang hal itu, orang harus menghindari membandingkan hal-hal yang tidak dari jenis yang sama; jika seseorang tertarik pada apakah konversi sesuatu ke bentuk umum akan memberikan hasil yang sama, ia harus melakukan konversi seperti itu secara eksplisit. Pertimbangkan, misalnya,
Ada tiga cara di mana seseorang mungkin ingin membandingkan
int
denganfloat
. Orang mungkin ingin tahu:float
yangint
cocok dengan cocokfloat
?float
pertandingan cocokint
?int
danfloat
mewakili nilai numerik yang sama.Jika seseorang mencoba membandingkan
int
danfloat
secara langsung, kode yang dikompilasi akan menjawab pertanyaan pertama; apakah itu yang dimaksudkan oleh programmer, akan jauh dari jelas. Mengubah perbandingan untuk(float)i == f
memperjelas bahwa makna pertama dimaksudkan, atau(double)i == (double)f
akan menyebabkan kode menjawab pertanyaan ketiga (dan membuatnya jelas itulah yang dimaksudkan).(*) Sekalipun spec C # menganggap nilai tipe misalnya
System.Int32
sebagai objek tipeSystem.Int32
, pandangan seperti itu bertentangan dengan persyaratan bahwa kode dijalankan pada platform yang specnya menganggap nilai dan objek sebagai penghuni alam semesta yang berbeda. Selanjutnya, jikaT
merupakan tipe referensi, danx
adalahT
, maka referensi tipeT
harus dapat merujukx
. Jadi, jika suatu variabelv
bertipeInt32
memegangObject
, suatu referensi bertipeObject
harus dapat menyimpan referensiv
atau isinya. Bahkan, referensi tipeObject
akan dapat menunjuk ke objek yang menyimpan data yang disalinv
, tetapi tidak untukv
dirinya sendiri atau kontennya. Itu tidak menyarankan keduanyav
atau isinya benar-benar sebuahObject
.sumber
the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Salah. Tidak seperti Java, C # tidak memiliki tipe primitif dan kotak yang terpisah. Ini sedang dikotakobject
karena itu satu-satunya kelebihan lainnyaEquals()
.float
. Casting afloat
to adouble
tidak akan secara ajaib menciptakan presisi baru.List<String>.Enumerator
dan objek bertipe heapList<String>.Enumerator
adalah sama, tetapi spesifikasi ECMA / CLI mengatakan mereka berbeda, dan bahkan ketika digunakan dalam C # mereka berperilaku berbeda.i
danf
masing-masing dikonversi kedouble
sebelum perbandingan, mereka akan menghasilkan 16777217.0 dan 16777216.0, yang dibandingkan sebagai tidak setara. Konversii
float
akan menghasilkan 16777216.0f, dibandingkan denganf
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. Jenis objek kotak yang sesuai dengan tipe nilai dapat memenuhi tipe parameterReferenceEquals
melalui identitas yang mempertahankan upcast; tipe lokasi penyimpanan, bagaimanapun, membutuhkan konversi yang tidak melindungi identitas . Jika melemparkanT
keU
menghasilkan referensi ke sesuatu selain yang asliT
, itu akan menyarankan kepada saya bahwaT
tidak benar-benar aU
.Equals () adalah metode System.Object Class
Syntax: Public virtual bool Equals ()
Rekomendasi jika kita ingin membandingkan keadaan dua objek maka kita harus menggunakan metode Equals ()
sebagaimana dinyatakan di atas jawaban == operator membandingkan nilainya sama.
Tolong jangan bingung dengan ReferenceEqual
Reference Equals ()
Sintaks: public static bool ReferenceEquals ()
Ini menentukan apakah instance objek yang ditentukan memiliki instance yang sama
sumber
Yang perlu Anda sadari adalah bahwa melakukan
==
akan selalu berakhir dengan memanggil metode. Pertanyaannya adalah apakah memanggil==
danEquals
akhirnya memanggil / melakukan hal yang sama.Dengan tipe referensi,
==
akan selalu memeriksa 1 apakah referensi sama (Object.ReferenceEquals
).Equals
di sisi lain dapat diganti dan dapat memeriksa apakah beberapa nilai sama.EDIT: untuk menjawab svick dan menambahkan komentar SLaks, berikut adalah beberapa kode IL
sumber
int
s dengan panggilan ==? Petunjuk: tidak adaoperator ==
metode untukInt32
, tetapi ada satu untukString
.==
tidak hanya melakukan sihir, pada akhirnya hanya memanggil metode (kebanyakan programmer mungkin tidak pernah mengimplementasikan / menimpa operator apa pun). Mungkin saya bisa menambahkan komentar ke pertanyaan Anda alih-alih menambahkan jawaban saya sendiri. Jangan ragu untuk memperbarui milik Anda jika Anda merasa apa yang saya katakan relevan.==
pada tipe primitif bukan operator kelebihan beban, tetapi fitur bahasa intrinsik yang mengkompilasiceq
instruksi IL.== Dalam Primitif
Dalam perbandingan primitif == operator berperilaku cukup jelas, Di C # ada banyak == operator kelebihan tersedia.
Jadi dalam hal ini tidak ada konversi tersirat dari
int
keshort
tetapishort
menjadiint
mungkin. Jadi newAge dikonversi menjadi int dan terjadi perbandingan yang mengembalikan nilai true karena keduanya memiliki nilai yang sama. Jadi itu setara dengan:.Equals () dalam Primitive
Di sini kita perlu melihat apa metode Equals (), kita memanggil Equals dengan variabel tipe pendek. Jadi ada tiga kemungkinan:
Jenis pertama tidak berlaku di sini karena jumlah argumen berbeda yang kami panggil dengan hanya satu argumen bertipe int. Ketiga juga dihilangkan seperti yang disebutkan di atas konversi int ke pendek tidak mungkin. Jadi di sini tipe kedua
Equals(object)
disebut. Theshort.Equals(object)
adalah:Jadi di sini kondisi diuji
z is short
yang salah karena z adalah int sehingga mengembalikan salah.Ini adalah artikel terperinci dari Eric Lippert
sumber