Semua kode yang ditulis dalam bahasa .NET mengkompilasi ke MSIL, tetapi apakah ada tugas / operasi khusus yang dapat Anda lakukan hanya menggunakan MSIL secara langsung?
Mari kita juga melakukan hal-hal yang lebih mudah dalam MSIL daripada C #, VB.NET, F #, j # atau bahasa .NET lainnya.
Sejauh ini kita punya ini:
- Rekursi ekor
- Co Generik / Kontravarian
- Kelebihan yang hanya berbeda dalam jenis pengembalian
- Timpa pengubah akses
- Memiliki kelas yang tidak dapat diwarisi dari System.Object
- Pengecualian yang difilter (dapat dilakukan di vb.net)
- Memanggil metode virtual dari tipe kelas statis saat ini.
- Dapatkan pegangan pada versi kotak dari tipe nilai.
- Lakukan percobaan / kesalahan.
- Penggunaan nama terlarang.
- Tentukan konstruktor tanpa parameter Anda sendiri untuk tipe nilai .
- Tentukan acara dengan
raise
elemen. - Beberapa konversi diizinkan oleh CLR tetapi tidak oleh C #.
- Jadikan
main()
metode non sebagai.entrypoint
. - bekerja dengan jenis asli
int
dan asliunsigned int
secara langsung. - Bermain dengan pointer sementara
- direktif emitbyte di MethodBodyItem
- Lempar dan tangkap bukan tipe System.Exception
- Warisan Enum (Tidak Diverifikasi)
- Anda dapat memperlakukan array byte sebagai array int (4x lebih kecil).
- Anda dapat memiliki bidang / metode / properti / acara semua memiliki nama yang sama (Tidak Diverifikasi).
- Anda bisa bercabang kembali menjadi blok percobaan dari blok tangkapnya sendiri.
- Anda memiliki akses ke specifier akses famandassem (
protected internal
is fam or assem) - Akses langsung ke
<Module>
kelas untuk mendefinisikan fungsi global, atau inisialisasi modul.
Jawaban:
MSIL memungkinkan untuk kelebihan yang hanya berbeda dalam jenis pengembalian karena
atau
sumber
Sebagian besar bahasa .Net termasuk C # dan VB tidak menggunakan fitur rekursi ekor dari kode MSIL.
Rekursi ekor adalah optimisasi yang umum dalam bahasa fungsional. Itu terjadi ketika metode A berakhir dengan mengembalikan nilai metode B sedemikian rupa sehingga tumpukan metode A dapat dibatalkan alokasi begitu panggilan ke metode B dibuat.
Kode MSIL mendukung rekursi ekor secara eksplisit, dan untuk beberapa algoritma ini bisa menjadi optimasi penting untuk dilakukan. Tetapi karena C # dan VB tidak menghasilkan instruksi untuk melakukan ini, itu harus dilakukan secara manual (atau menggunakan F # atau bahasa lain).
Berikut adalah contoh bagaimana rekursi ekor dapat diimplementasikan secara manual dalam C #:
Ini adalah praktik umum untuk menghapus rekursi dengan memindahkan data lokal dari tumpukan perangkat keras ke struktur data tumpukan yang dialokasikan tumpukan. Dalam penghapusan rekursi ekor-panggilan seperti yang ditunjukkan di atas, tumpukan dihilangkan sepenuhnya, yang merupakan optimasi yang cukup bagus. Juga, nilai kembali tidak harus berjalan lama, tetapi dikembalikan langsung.
Tetapi, bagaimanapun, CIL menyediakan fitur ini sebagai bagian dari bahasa, tetapi dengan C # atau VB harus diimplementasikan secara manual. (Jitter juga bebas untuk membuat pengoptimalan ini sendiri, tetapi itu adalah masalah lain.)
sumber
Di MSIL, Anda bisa memiliki kelas yang tidak bisa mewarisi dari System.Object.
Kode contoh: kompilasi dengan ilasm.exe PEMBARUAN: Anda harus menggunakan "/ NOAUTOINHERIT" untuk mencegah assembler dari pewarisan otomatis.
sumber
TypeLoadException
). PEVerify pengembalian: [MD]: Kesalahan: TypeDef yang bukan Antarmuka dan bukan kelas Objek memperluas token Nil.Dimungkinkan untuk menggabungkan
protected
daninternal
mengakses pengubah. Dalam C #, jika Anda menulisprotected internal
anggota dapat diakses dari majelis dan dari kelas turunan. Melalui MSIL Anda bisa mendapatkan anggota yang hanya dapat diakses dari kelas turunan dalam majelis saja . (Saya pikir itu bisa sangat berguna!)sumber
private protected
Ooh, saya tidak melihat ini saat itu. (Jika Anda menambahkan tag jon-skeet itu lebih cenderung, tapi saya tidak sering memeriksanya.)
Sepertinya Anda sudah mendapat jawaban yang cukup bagus. Sebagai tambahan:
object
dalam C #, ini kadang-kadang akan berfungsi. Lihat pertanyaan [] / int [] SO sebagai contoh.Saya akan menambahkan ini jika saya memikirkan hal lain ...
sumber
<>a
sebutkan sebagai nama dalam C # ...CLR sudah mendukung co / contravariance umum, tetapi C # tidak mendapatkan fitur ini sampai 4.0
sumber
Di IL, Anda dapat melempar dan menangkap jenis apa pun, bukan hanya jenis yang berasal
System.Exception
.sumber
try
/catch
tanpa tanda kurung di catch-statement Anda juga akan menangkap pengecualian yang tidak seperti pengecualian. Melempar, bagaimanapun, memang hanya mungkin ketika Anda mewarisi dariException
.IL memiliki perbedaan antara
call
dancallvirt
untuk pemanggilan metode virtual. Dengan menggunakan yang pertama Anda dapat memaksa memanggil metode virtual dari tipe kelas statis saat ini daripada fungsi virtual dalam tipe kelas dinamis.C # tidak memiliki cara untuk melakukan ini:
VB, seperti IL, dapat mengeluarkan panggilan nonvirtual dengan menggunakan
MyClass.Method()
sintaks. Di atas, ini akan menjadiMyClass.ToString()
.sumber
Dalam try / catch, Anda dapat memasukkan kembali blok try dari blok catch-nya sendiri. Jadi, Anda bisa melakukan ini:
AFAIK Anda tidak dapat melakukan ini dalam C # atau VB
sumber
GOTO
Catch
keTry
. Jalankan kode uji online di sini .Dengan IL dan VB.NET Anda dapat menambahkan filter saat mendapatkan pengecualian, tetapi C # v3 tidak mendukung fitur ini.
Contoh VB.NET ini diambil dari http://blogs.msdn.com/clrteam/archive/2009/02/05/catch-rethrow-and-filters-why-you-should-care.aspx (perhatikan
When ShouldCatch(ex) = True
di Tangkap klausa):sumber
= True
, itu membuat mataku berdarah!Sejauh yang saya tahu, tidak ada cara untuk membuat inisialisasi modul (konstruktor statis untuk seluruh modul) langsung di C #:
http://blogs.msdn.com/junfeng/archive/2005/11/19/494914.aspx
sumber
Native types
Anda dapat bekerja dengan int asli dan tipe int unsigned asli secara langsung (di c # Anda hanya dapat bekerja pada IntPtr yang tidak sama.
Transient Pointers
Anda dapat bermain dengan pointer sementara, yang merupakan pointer ke tipe yang dikelola tetapi dijamin tidak bergerak dalam memori karena mereka tidak ada dalam tumpukan yang dikelola. Tidak sepenuhnya yakin bagaimana Anda bisa menggunakan ini tanpa mengotak-atik kode yang tidak dikelola tetapi tidak terpapar ke bahasa lain secara langsung hanya melalui hal-hal seperti stackalloc.
<Module>
Anda dapat mengacau dengan kelas jika Anda menginginkannya (Anda dapat melakukan ini dengan refleksi tanpa perlu IL)
.emitbyte
.entrypoint
Anda memiliki sedikit lebih banyak fleksibilitas dalam hal ini, Anda dapat menerapkannya pada metode yang tidak disebut Utama misalnya.
membaca spec saya yakin Anda akan menemukan beberapa lagi.
sumber
<Module>
dimaksudkan sebagai kelas khusus untuk bahasa yang menerima metode global (seperti yang dilakukan VB), tetapi memang, C # tidak dapat mengaksesnya secara langsung.Anda dapat meretas metode override co / contra-variance, yang tidak diizinkan oleh C # (ini BUKAN sama dengan varian umum!). Saya mendapat informasi lebih lanjut tentang penerapan ini di sini , dan bagian 1 dan 2
sumber
Saya pikir yang saya terus berharap (dengan alasan yang sepenuhnya salah) adalah warisan di Enums. Sepertinya bukan hal yang sulit untuk dilakukan di SMIL (karena Enums hanyalah kelas) tetapi itu bukan sesuatu yang sintaks C # ingin Anda lakukan.
sumber
Inilah beberapa lagi:
sumber
20) Anda dapat memperlakukan array byte sebagai array int (4x lebih kecil).
Saya menggunakan ini baru-baru ini untuk melakukan implementasi XOR cepat, karena fungsi CLR xor beroperasi pada int dan saya perlu melakukan XOR pada aliran byte.
Kode yang dihasilkan diukur menjadi ~ 10x lebih cepat dari yang dilakukan di C # (melakukan XOR pada setiap byte).
===
Saya tidak punya cukup stackoverflow street credz untuk mengedit pertanyaan dan menambahkan ini ke daftar sebagai # 20, jika orang lain bisa membengkak ;-)
sumber
Obfuscator sesuatu menggunakan - Anda dapat memiliki bidang / metode / properti / acara semua memiliki nama yang sama.
sumber
Warisan enum tidak benar-benar mungkin:
Anda bisa mewarisi dari kelas Enum. Tetapi hasilnya tidak berperilaku seperti Enum pada khususnya. Bahkan berperilaku tidak seperti tipe nilai, tetapi seperti kelas biasa. Yang srange adalah: IsEnum: True, IsValueType: True, IsClass: False
Tapi itu tidak terlalu berguna (kecuali jika Anda ingin membingungkan seseorang atau runtime itu sendiri.)
sumber
Anda juga bisa mendapatkan kelas dari delegasi System.Multicast di IL, tetapi Anda tidak bisa melakukan ini di C #:
sumber
Anda juga dapat mendefinisikan metode tingkat modul (alias global) di IL, dan C #, sebaliknya, hanya memungkinkan Anda untuk menentukan metode selama metode tersebut melekat pada setidaknya satu jenis.
sumber