Mengapa saya bisa lulus 1 sebagai pendek, tetapi bukan variabel int saya?

146

Mengapa Tulis pertama dan kedua berfungsi tetapi bukan yang terakhir? Apakah ada cara saya bisa mengizinkan mereka bertiga dan mendeteksi apakah itu 1, (int) 1 atau saya lewat? Dan benar-benar mengapa satu diperbolehkan tetapi yang terakhir? Yang kedua diizinkan tetapi bukan yang terakhir benar-benar menghantam pikiran saya.

Demo untuk menampilkan kesalahan kompilasi

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}
CodesInChaos
sumber
2
Saya juga bingung dengan ini, saya sering harus memberikan int untuk panggilan fungsi meskipun mereka harus dicast ...
Mathieu Dumoulin
2
@MathieuDumoulin mereka adalah castable, itu sebabnya Anda bisa melemparkan mereka. Tetapi ini adalah konversi yang merugikan (ada banyak int yang tidak cocok secara singkat), jadi pemeran implisit tidak mungkin, itu sebabnya Anda harus menulis (short) i.
Abel

Jawaban:

186

Dua yang pertama adalah ekspresi konstan, yang terakhir tidak.

Spesifikasi C # memungkinkan konversi implisit dari int ke kependekan untuk konstanta, tetapi tidak untuk ekspresi lainnya. Ini adalah aturan yang masuk akal, karena untuk konstanta kompiler dapat memastikan bahwa nilai cocok dengan tipe target, tetapi tidak bisa untuk ekspresi normal.

Aturan ini sejalan dengan pedoman bahwa konversi implisit harus tanpa kerugian.

6.1.8 Konversi ekspresi konstan yang implisit

Konversi ekspresi konstan implisit memungkinkan konversi berikut:

  • Sebuah konstan-ekspresi (§7.18) jenis intdapat dikonversi untuk mengetik sbyte, byte, short, ushort, uint, atau ulong, asalkan nilai konstan ekspresi adalah dalam kisaran jenis tujuan.
  • Sebuah konstan-ekspresi dari tipe longdapat dikonversi ke jenis ulong, asalkan nilai konstan ekspresi tidak negatif.

(Dikutip dari C # Language Spesifikasi Versi 3.0)

CodesInChaos
sumber
67

Tidak ada konversi implisit dari intke shortkarena kemungkinan pemotongan. Namun, ekspresi konstan dapat dianggap sebagai tipe target oleh kompiler .

1? Bukan masalah: itu jelas shortnilai yang valid . i? Tidak terlalu banyak - itu bisa berupa nilai> short.MaxValuemisalnya, dan kompiler tidak dapat mengeceknya dalam kasus umum.

Konrad Rudolph
sumber
Jadi ... tidak masalah seberapa eksplisit saya ...> _ <. Apakah Anda tahu jika saya dapat mendeteksi apakah litereal disahkan atau variabel int?
@ acidzombie24 Anda tidak bisa. Tetapi mengapa Anda ingin melakukan itu?
Adam Houldsworth
@ acidzombie24 Saya rasa Anda tidak bisa mendeteksinya. Namun Anda dapat menggunakan argumen templat dan kemudian menggunakan refleksi untuk mendapatkan tipenya.
Konrad Rudolph
3
@ acidzombie24 Tidak mungkin literal bisa dilewati saat runtime. Jadi Anda bisa menggunakan mata Anda untuk memeriksa pada waktu kompilasi.
Justin
1
@ acidzombie24 Dalam hal itu, apakah itu akan menjadi opsi untuk menerima argumen sebagai Expression<Func<int>>? Kemudian Anda bisa melewati () => 1atau () => idan di dalam fungsi Anda bisa memeriksa apakah entitas yang lulus berisi variabel yang ditangkap atau nilai konstan.
Konrad Rudolph
8

sebuah int literal dapat secara implisit dikonversi ke short. Sedangkan:

Anda tidak dapat secara implisit mengkonversi tipe numerik nonliteral dari ukuran penyimpanan yang lebih besar menjadi pendek

Jadi, dua karya pertama karena konversi implisit literal diperbolehkan.

Damien_The_Unbeliever
sumber
3
Jawaban Anda sedikit salah. Anda tidak harus menggunakan ekspresi literal tetapi konstan . Secara khusus contoh kedua bukan literal .
CodesInChaos
6

Saya percaya itu karena Anda memberikan literal / konstanta di dua yang pertama, tetapi tidak ada konversi tipe otomatis ketika melewati dalam bilangan bulat di ketiga.

Sunting: Seseorang mengalahkan saya untuk itu!

Justin
sumber
3

Karena tidak akan ada konversi implisit antara tipe Nonliteral ke ukuran pendek yang lebih besar.

Konversi tersirat hanya mungkin untuk ekspresi konstan.

public static void Write(short v) { }

Di mana Anda memberikan integernilai sebagai argumenshort

int i=1;
Write(i);  //Which is Nonliteral here
Vishal Suthar
sumber
3

Kompiler telah memberi tahu Anda mengapa kode gagal:

cannot convert `int' expression to type `short'

Jadi, inilah pertanyaan yang harus Anda tanyakan: mengapa konversi ini gagal? Saya googled "c # convert int short" dan berakhir di halaman MS C # untuk shortkata kunci:

http://msdn.microsoft.com/en-us/library/ybs77ex4(v=vs.71).aspx

Seperti yang dikatakan halaman ini, gips implisit dari tipe data yang lebih besar shorthanya diizinkan untuk literal. Kompiler dapat mengetahui kapan literal berada di luar jangkauan, tetapi tidak sebaliknya, sehingga perlu diyakinkan bahwa Anda telah menghindari kesalahan di luar jangkauan dalam logika program Anda. Jaminan itu disediakan oleh para pemain.

Write((short)i)
Isaac Rabinovitch
sumber
0

Konversi dari int -> short dapat mengakibatkan pemotongan data. Itu sebabnya.

ak1238
sumber