Kode berikut salah (lihat di ideone ):
public class Test
{
public static void Main()
{
int j = 5;
(j++); // if we remove the "(" and ")" then this compiles fine.
}
}
kesalahan CS0201: Hanya penugasan, panggilan, kenaikan, penurunan, menunggu, dan ekspresi objek baru yang dapat digunakan sebagai pernyataan
- Mengapa kode dikompilasi ketika kita menghapus tanda kurung?
- Mengapa tidak dikompilasi dengan tanda kurung?
- Mengapa C # didesain seperti itu?
c#
syntax
expression
language-design
parentheses
pengguna10607
sumber
sumber
Jawaban:
Saya akan melakukan yang terbaik.
Seperti jawaban lain yang dicatat, apa yang terjadi di sini adalah kompiler mendeteksi bahwa ekspresi sedang digunakan sebagai pernyataan . Dalam banyak bahasa - C, JavaScript, dan banyak lainnya - sangat sah untuk menggunakan ekspresi sebagai pernyataan.
2 + 2;
legal dalam bahasa-bahasa ini, meskipun ini adalah pernyataan yang tidak berpengaruh. Beberapa ekspresi hanya berguna untuk nilainya, beberapa ekspresi hanya berguna untuk efek sampingnya (seperti panggilan ke metode pengembalian batal) dan beberapa ekspresi, sayangnya, berguna untuk keduanya. (Seperti kenaikan.)Poinnya adalah: pernyataan yang hanya terdiri dari ekspresi hampir pasti kesalahan kecuali jika ekspresi itu biasanya dianggap lebih berguna untuk efek sampingnya daripada nilainya . Desainer C # ingin menemukan jalan tengah, dengan memungkinkan ekspresi yang umumnya dianggap sebagai efek samping, sementara melarang mereka yang juga biasanya dianggap berguna untuk nilai-nilai mereka. Rangkaian ekspresi yang mereka identifikasi dalam C # 1.0 adalah kenaikan, penurunan, pemanggilan metode, penugasan, dan agak kontroversial, pemanggilan konstruktor.
ASIDE: Orang biasanya menganggap konstruksi objek sebagai nilai yang dihasilkannya, bukan untuk efek samping konstruksi; menurut saya memungkinkan
new Foo();
adalah sedikit kesalahan. Secara khusus, saya telah melihat pola ini dalam kode dunia nyata yang menyebabkan cacat keamanan:Bisa jadi sangat sulit untuk menemukan cacat ini jika kodenya rumit.
Oleh karena itu kompiler berfungsi untuk mendeteksi semua pernyataan yang terdiri dari ekspresi yang tidak ada dalam daftar itu. Secara khusus, ekspresi dalam tanda kurung diidentifikasi hanya dengan itu - ekspresi dalam tanda kurung. Mereka tidak ada dalam daftar "diizinkan sebagai ekspresi pernyataan", sehingga mereka tidak diizinkan.
Semua ini demi prinsip desain bahasa C #. Jika Anda mengetik,
(x++);
Anda mungkin melakukan kesalahan . Ini mungkin salah ketikM(x++);
atau sesuatu yang adil. Ingat, sikap tim kompiler C # bukanlah " bisakah kita mencari cara untuk membuat ini berhasil? " Sikap tim kompiler C # adalah " jika kode yang masuk akal tampak seperti kesalahan yang mungkin terjadi, mari beri tahu pengembang ". Pengembang C # menyukai sikap itu.Sekarang, semua yang mengatakan, sebenarnya ada sebuah kasus aneh beberapa di mana C # spesifikasi yang menyiratkan atau negara langsung yang kurung dianulir tetapi C # compiler memungkinkan mereka anyways. Dalam hampir semua kasus perbedaan kecil antara perilaku yang ditentukan dan perilaku yang diizinkan benar-benar tidak berbahaya, sehingga penulis kompiler tidak pernah memperbaiki bug kecil ini. Anda dapat membaca tentang itu di sini:
Apakah ada perbedaan antara return myVar vs return (myVar)?
sumber
... ? ... : ...
, di mana perbaikannya menggunakanif
/else
sebagai gantinya.)contineu;
.try { new Foo(null); } catch (ArgumentNullException)...
tapi jelas situasi ini secara definisi bukan kode produksi. Tampaknya masuk akal bahwa kode tersebut dapat ditulis untuk menetapkan variabel dummy.Dalam spesifikasi bahasa C #
Menempatkan tanda kurung di sekitar pernyataan menciptakan ekspresi yang disebut tanda kurung baru. Dari spesifikasi:
Karena ekspresi yang ditulis dalam tanda kurung tidak terdaftar sebagai pernyataan ekspresi yang valid, itu bukan pernyataan yang valid sesuai dengan spesifikasi. Mengapa para perancang memilih untuk melakukannya dengan cara ini adalah dugaan siapa pun, tetapi taruhan saya adalah karena kurung tidak berfungsi jika seluruh pernyataan terkandung dalam kurung:
stmt
dan(stmt)
persis sama.sumber
OP
tidak bertanya apa-apa tentang desain bahasa. Dia hanya ingin tahu mengapa ini kesalahan. Jawabannya adalah: karena itu bukan pernyataan yang valid .karena kurung di sekitar
i++
sedang membuat / mendefinisikan ekspresi .. seperti pesan kesalahan mengatakan .. ekspresi sederhana tidak dapat digunakan sebagai pernyataan.mengapa bahasanya dirancang seperti ini? untuk mencegah bug, memiliki ekspresi yang menyesatkan sebagai pernyataan, yang tidak menghasilkan efek samping seperti memiliki kode
baris kedua tidak berpengaruh (tetapi Anda mungkin tidak memperhatikan). Tapi bukannya kompiler menghapusnya (karena kode tidak diperlukan). Itu secara eksplisit meminta Anda untuk menghapusnya (sehingga Anda akan menyadari atau kesalahan) ATAU memperbaikinya jika Anda lupa mengetik sesuatu.
edit :
untuk membuat bagian tentang tanda kurung menjadi lebih jelas .. tanda kurung dalam c # (selain kegunaan lain, seperti pemeran dan pemanggilan fungsi), digunakan untuk mengelompokkan ekspresi, dan mengembalikan satu ekspresi (membuat sub ekspresi).
pada level kode itu hanya stament yang diizinkan .. jadi
tetapi dengan menggunakan tanda kurung Anda mengubahnya menjadi ekspresi
dan ini
tidak valid karena kompiler tidak dapat memastikan bahwa ekspresi sebagai efek samping (bukan tanpa menimbulkan masalah penghentian) ..
sumber
j
variabel kan?j++;
adalah pernyataan yang valid, tetapi dengan menggunakan tanda kurung yang Anda ucapkanlet me take this stement and turn it into an expression
.. dan ekspresi tidak valid pada saat itu dalam kode