Saya seorang pemula C # dan saya baru saja mengalami masalah. Ada perbedaan antara C # dan Java saat berhadapan dengan operator terner ( ? :
).
Di segmen kode berikut, mengapa baris ke-4 tidak berfungsi? Kompilator menampilkan pesan kesalahan there is no implicit conversion between 'int' and 'string'
. Baris ke-5 juga tidak berfungsi. Keduanya List
adalah objek, bukan?
int two = 2;
double six = 6.0;
Write(two > six ? two : six); //param: double
Write(two > six ? two : "6"); //param: not object
Write(two > six ? new List<int>() : new List<string>()); //param: not object
Namun, kode yang sama berfungsi di Java:
int two = 2;
double six = 6.0;
System.out.println(two > six ? two : six); //param: double
System.out.println(two > six ? two : "6"); //param: Object
System.out.println(two > six ? new ArrayList<Integer>()
: new ArrayList<String>()); //param: Object
Fitur bahasa apa di C # yang hilang? Jika ada, mengapa tidak ditambahkan?
java
c#
ternary-operator
conditional-operator
blackr1234
sumber
sumber
int
bukan objek. Itu primitif.ArrayList<String>
danArrayList<Integer>
menjadi hanyaArrayList
di bytecode. Ini berarti bahwa mereka tampak memiliki tipe yang sama persis pada waktu proses. Ternyata di C # mereka berbeda tipe.Jawaban:
Melihat melalui C # 5 Spesifikasi Bahasa bagian 7.14: Operator Bersyarat kita dapat melihat yang berikut:
Dengan kata lain: ia mencoba untuk menemukan apakah x dan y dapat dikonversi ke eachother dan jika tidak, kesalahan kompilasi terjadi. Dalam kasus kami
int
danstring
tidak memiliki konversi eksplisit atau implisit sehingga tidak dapat dikompilasi.Bandingkan ini dengan Spesifikasi Bahasa Java 7 bagian 15.25: Operator Bersyarat :
Dan, lihat bagian 15.12.2.7. Argumen Tipe Inferensi Berdasarkan Argumen Aktual, kita dapat melihat mencoba untuk menemukan nenek moyang yang sama yang akan berfungsi sebagai tipe yang digunakan untuk panggilan yang mendarat dengannya
Object
.Object
adalah argumen yang dapat diterima sehingga panggilan tersebut akan berhasil.sumber
Jawaban yang diberikan bagus; Saya akan menambahkan kepada mereka bahwa aturan C # ini adalah konsekuensi dari pedoman desain yang lebih umum. Ketika diminta untuk menyimpulkan jenis ekspresi dari salah satu dari beberapa pilihan, C # memilih yang terbaik dan unik dari mereka . Artinya, jika Anda memberi C # beberapa pilihan seperti "Jerapah, Mamalia, Hewan", maka C # dapat memilih yang paling umum - Hewan - atau mungkin memilih yang paling spesifik - Jerapah - bergantung pada situasinya. Tapi itu harus memilih salah satu pilihan yang diberikan . C # tidak pernah mengatakan "pilihan saya adalah antara Kucing dan Anjing, oleh karena itu saya akan menyimpulkan bahwa Hewan adalah pilihan terbaik". Itu bukan pilihan yang diberikan, jadi C # tidak bisa memilihnya.
Dalam kasus operator terner C # mencoba untuk memilih tipe yang lebih umum dari int dan string, tetapi tidak ada tipe yang lebih umum. Daripada memilih tipe yang bukan merupakan pilihan di tempat pertama, seperti objek, C # memutuskan bahwa tidak ada tipe yang dapat disimpulkan.
Saya perhatikan juga bahwa ini sesuai dengan prinsip desain C # lainnya: jika ada yang salah, beri tahu pengembang. Bahasa tidak mengatakan "Saya akan menebak apa yang Anda maksud dan mengacaukannya jika saya bisa". Bahasa mengatakan "Saya pikir Anda telah menulis sesuatu yang membingungkan di sini, dan saya akan memberitahu Anda tentang itu."
Juga, saya perhatikan bahwa C # tidak beralasan dari variabel ke nilai yang diberikan , melainkan ke arah lain. C # tidak mengatakan "Anda menugaskan ke variabel objek oleh karena itu ekspresi harus dapat diubah menjadi objek, oleh karena itu saya akan memastikan bahwa itu". Sebaliknya, C # mengatakan "ekspresi ini harus memiliki tipe, dan saya harus dapat menyimpulkan bahwa tipe tersebut kompatibel dengan objek". Karena ekspresi tidak memiliki tipe, kesalahan dihasilkan.
sumber
int? b = (a != 0 ? a : (int?) null)
. Ada juga pertanyaan ini , bersama dengan semua pertanyaan terkait di sampingnya. Jika Anda terus mengikuti tautan, ada cukup banyak. Sebagai perbandingan, saya belum pernah mendengar seseorang mengalami masalah dunia nyata dengan cara Java melakukannya.Mengenai bagian generik:
Dalam C #, kompilator mencoba untuk mengubah bagian ekspresi kanan menjadi beberapa tipe umum; karena
List<int>
danList<string>
merupakan dua tipe konstruksi yang berbeda, yang satu tidak dapat dikonversi ke yang lain.Di Java, kompilator mencoba menemukan supertipe umum daripada mengonversinya, jadi kompilasi kode melibatkan penggunaan implisit wildcard dan penghapusan tipe ;
memiliki tipe kompilasi
ArrayList<?>
(sebenarnya, bisa jugaArrayList<? extends Serializable>
atauArrayList<? extends Comparable<?>>
, bergantung pada konteks penggunaan, karena keduanya adalah supertipe generik umum) dan tipe waktu proses mentahArrayList
(karena ini adalah supertipe raw umum).Misalnya (uji sendiri) ,
sumber
Write(two > six ? new List<object>() : new List<string>());
tidak berhasil juga.ArrayList<String>
danArrayList<Integer>
akan menjadiArrayList
(tipe mentah), tetapi tipe yang disimpulkan untuk operator terner ini adalahArrayList<?>
(tipe wildcard). Secara lebih umum, runtime Java yang mengimplementasikan generik melalui penghapusan tipe tidak berpengaruh pada tipe waktu kompilasi ekspresi.two > six ? new ArrayList<Integer>() : new ArrayList<String>()
isArrayList<? extends Serializable&Comparable<?>>
yang berarti Anda dapat menugaskannya ke variabel tipeArrayList<? extends Serializable>
dan juga variabel tipeArrayList<? extends Comparable<?>>
, tapi tentu sajaArrayList<?>
, yang setara denganArrayList<? extends Object>
, berfungsi juga.Baik di Java dan C # (dan sebagian besar bahasa lainnya), hasil ekspresi memiliki tipe. Dalam kasus operator terner, ada dua kemungkinan subekspresi yang dievaluasi untuk hasil dan keduanya harus memiliki jenis yang sama. Dalam kasus Java,
int
variabel dapat diubah menjadiInteger
dengan autoboxing. Sekarang karena keduanyaInteger
danString
mewarisi dariObject
, keduanya dapat dikonversi ke jenis yang sama dengan konversi penyempitan sederhana.Di sisi lain, di C #, an
int
adalah primitif dan tidak ada konversi implisit kestring
atau yang lainnyaobject
.sumber
int
menjadiobject
.Integer/String
keObject
bukanlah konversi yang menyempit, justru sebaliknya :-)Integer
danString
juga menerapkanSerializable
danComparable
jadi tugas untuk salah satu dari mereka akan bekerja dengan baik, misalnyaComparable<?> c=condition? 6: "6";
atauList<? extends Serializable> l = condition? new ArrayList<Integer>(): new ArrayList<String>();
yang kode Java hukum.Ini sangat mudah. Tidak ada konversi implisit antara string dan int. operator terner membutuhkan dua operan terakhir untuk memiliki tipe yang sama.
Mencoba:
sumber