Sebelumnya saya mengajukan pertanyaan tentang mengapa saya melihat begitu banyak contoh menggunakan var
kata kunci dan mendapatkan jawaban bahwa sementara itu hanya diperlukan untuk jenis anonim, namun tetap digunakan untuk membuat kode penulisan 'lebih cepat' / lebih mudah dan 'hanya karena'.
Mengikuti tautan ini ("C # 3.0 - Var Isn't Objec") Saya melihat bahwa var
dikompilasi ke tipe yang benar di IL (Anda akan melihatnya tentang artikel di tengah jalan).
Pertanyaan saya adalah berapa banyak lagi, jika ada, kode IL tidak menggunakan var
kata kunci, dan apakah akan mendekati tingkat yang terukur pada kinerja kode jika digunakan di mana-mana?
c#
performance
variables
var
Jeff Keslinke
sumber
sumber
var
pasti bekerja dengan "Temukan Semua Referensi" di Visual Studio 2019, jadi jika itu pernah rusak itu telah diperbaiki. Tetapi saya dapat mengonfirmasi bahwa itu berfungsi sejauh Visual Studio 2012, jadi saya tidak yakin mengapa Anda mengklaim itu tidak berfungsi.var
tidak akan dianggap sebagai referensiX
ketika Anda menggunakan "Temukan Semua Referensi" diX
. Menariknya, jika Anda menggunakan "Temukan Semua Referensi" divar
dalam pernyataan itu, itu akan menunjukkan kepada Anda referensiX
(meskipun masih tidak mencantumkanvar
pernyataan). Selain itu, ketika kursor aktifvar
, kursor akan menyorot semua contohX
dalam dokumen yang sama (dan sebaliknya).Jawaban:
Tidak ada kode IL tambahan untuk
var
kata kunci: IL yang dihasilkan harus identik untuk jenis non-anonim. Jika kompiler tidak dapat membuat IL itu karena tidak dapat mengetahui tipe apa yang ingin Anda gunakan, Anda akan mendapatkan kesalahan kompiler.Satu-satunya trik adalah bahwa
var
akan menyimpulkan jenis yang tepat di mana Anda mungkin telah memilih jenis antarmuka atau orang tua jika Anda mengatur jenis secara manual.Perbarui 8 Tahun Kemudian
Saya perlu memperbarui ini karena pemahaman saya telah berubah. Saya sekarang percaya mungkin untuk
var
mempengaruhi kinerja dalam situasi di mana metode mengembalikan antarmuka, tetapi Anda akan menggunakan tipe yang tepat. Misalnya, jika Anda memiliki metode ini:Pertimbangkan tiga baris kode ini untuk memanggil metode:
Ketiganya mengkompilasi dan mengeksekusi seperti yang diharapkan. Namun, dua baris pertama tidak persis sama, dan baris ketiga akan cocok dengan yang kedua, bukan yang pertama. Karena tanda tangan
Foo()
adalah untuk mengembalikan suatuIList<int>
, itu adalah bagaimana kompiler akan membangunbar3
variabel.Dari sudut pandang kinerja, sebagian besar Anda tidak akan melihat. Namun, ada situasi di mana kinerja baris ketiga mungkin tidak secepat kinerja yang pertama . Saat Anda terus menggunakan
bar3
variabel, kompiler mungkin tidak dapat mengirimkan panggilan metode dengan cara yang sama.Perhatikan bahwa mungkin (bahkan mungkin) jitter akan dapat menghapus perbedaan ini, tetapi tidak dijamin. Secara umum, Anda masih harus mempertimbangkan
var
untuk menjadi non-faktor dalam hal kinerja. Sama sekali tidak seperti menggunakandynamic
variabel. Tetapi untuk mengatakan itu tidak pernah membuat perbedaan sama sekali mungkin melebih-lebihkan itu.sumber
var i = 42;
(infers tipe int) TIDAK identik denganlong i = 42;
. Jadi dalam beberapa kasus Anda mungkin membuat asumsi yang salah tentang inferensi tipe. Ini dapat menyebabkan kesalahan runtime case sulit dipahami / tepi jika nilai tidak cocok. Karena alasan itu, mungkin masih merupakan ide yang baik untuk menjadi eksplisit ketika nilainya tidak memiliki tipe eksplisit. Jadi misalnya,var x = new List<List<Dictionary<int, string>()>()>()
akan dapat diterima, tetapivar x = 42
agak ambigu dan harus ditulis sebagaiint x = 42
. Tetapi untuk masing-masing mereka sendiri ...var x = 42;
tidak ambigu. Literal integer adalah tipeint
. Jika Anda ingin panjang literal Anda menulisvar x = 42L;
.Foo
mengembalikan aList
, daripada aIList
, maka ketiga baris akan mengkompilasi tetapi baris ketiga akan berperilaku seperti baris pertama , bukan yang kedua.Seperti kata Joel, kompiler bekerja pada waktu kompilasi jenis var apa yang seharusnya, secara efektif itu hanya sebuah trik yang dilakukan oleh kompiler untuk menghemat penekanan tombol, jadi misalnya
digantikan oleh
oleh kompiler sebelum IL dihasilkan. IL yang Dihasilkan akan persis sama seperti jika Anda mengetikkan string.
sumber
Karena belum ada yang menyebut reflektor ...
Jika Anda mengkompilasi kode C # berikut:
Kemudian gunakan reflektor di atasnya, Anda mendapatkan:
Jadi jawabannya jelas tidak ada kinerja runtime hit!
sumber
Untuk metode berikut:
Output IL adalah ini:
sumber
Compiler C # menyimpulkan tipe sebenarnya dari
var
variabel pada waktu kompilasi. Tidak ada perbedaan dalam IL yang dihasilkan.sumber
Jadi, untuk lebih jelasnya, ini adalah gaya pengkodean yang malas. Saya lebih suka tipe asli, diberi pilihan; Saya akan mengambil sedikit tambahan "noise" untuk memastikan saya menulis dan membaca apa yang saya pikir saya pada waktu kode / debug. * mengangkat bahu *
sumber
var
mempengaruhi kinerja sama sekali; Anda hanya menyatakan pendapat Anda tentang apakah orang harus menggunakannya.int
karena itu tidak dapat secara otomatis mengonversinyafloat
, tapi itu persis sama dengan yang akan terjadi jika Anda secara eksplisit digunakanint
dan kemudian diubah menjadifloat
. Bagaimanapun, jawaban Anda masih tidak menjawab pertanyaan "apakah menggunakanvar
mempengaruhi kinerja?" (khususnya dalam hal IL yang dihasilkan)Saya pikir Anda tidak mengerti apa yang Anda baca. Jika akan dikompilasi untuk jenis yang tepat, maka adalah tidak ada perbedaan. Ketika saya melakukan ini:
Kompiler tahu itu int, dan menghasilkan kode seolah-olah saya telah menulis
Seperti yang Anda tautkan dengan posting, itu dikompilasi dengan tipe yang sama. Ini bukan pemeriksaan runtime atau apa pun yang membutuhkan kode tambahan. Kompilator hanya mengetahui apa jenisnya, dan menggunakannya.
sumber
Tidak ada biaya kinerja runtime untuk menggunakan var. Meskipun, saya menduga ada biaya kinerja kompilasi karena kompiler perlu menyimpulkan jenisnya, meskipun ini kemungkinan besar akan diabaikan.
sumber
Jika kompiler dapat melakukan inferencing tipe otomatis, maka tidak akan ada masalah dengan kinerja. Keduanya akan menghasilkan kode yang sama
Namun, jika Anda membangun tipe secara dinamis (LINQ ...) maka itu
var
adalah satu-satunya pertanyaan Anda dan ada mekanisme lain untuk membandingkan untuk mengatakan apa hukumannya.sumber
Saya selalu menggunakan kata var dalam artikel web atau memandu tulisan.
Lebar editor teks artikel online kecil.
Jika saya menulis ini:
Anda akan melihat bahwa teks kode pra yang dirender di atas terlalu panjang dan keluar dari kotak, sehingga disembunyikan. Pembaca perlu menggulir ke kanan untuk melihat sintaksis lengkap.
Itu sebabnya saya selalu menggunakan kata kunci var dalam tulisan artikel web.
Seluruh kode pra yang diberikan hanya muat di dalam layar.
Dalam praktiknya, untuk mendeklarasikan objek, saya jarang menggunakan var, saya mengandalkan intellisense untuk mendeklarasikan objek lebih cepat.
Contoh:
Tapi, untuk mengembalikan objek dari suatu metode, saya menggunakan var untuk menulis kode lebih cepat.
Contoh:
sumber
"var" adalah salah satu hal yang disukai atau dibenci orang (seperti wilayah). Padahal, tidak seperti wilayah, var mutlak diperlukan saat membuat kelas anonim.
Bagi saya, var masuk akal ketika Anda membuat objek secara langsung seperti:
Yang sedang berkata, Anda dapat dengan mudah melakukan:
Dictionary<string, string> dict =
baru dan intellisense akan mengisi sisanya untuk Anda di sini.Jika Anda hanya ingin bekerja dengan antarmuka tertentu, maka Anda tidak dapat menggunakan var kecuali metode yang Anda panggil mengembalikan antarmuka secara langsung.
Resharper tampaknya berada di sisi menggunakan "var" di seluruh, yang dapat mendorong lebih banyak orang untuk melakukannya dengan cara itu. Tetapi saya agak setuju bahwa lebih sulit untuk membaca jika Anda memanggil suatu metode dan tidak jelas apa yang dikembalikan oleh namanya.
var sendiri tidak memperlambat apa pun, tetapi ada satu peringatan untuk ini yang tidak dipikirkan banyak orang. Jika Anda melakukannya
var result = SomeMethod();
maka kode setelah itu mengharapkan semacam hasil kembali di mana Anda akan memanggil berbagai metode atau properti atau apa pun. JikaSomeMethod()
mengubah definisinya menjadi beberapa tipe lain tetapi masih memenuhi kontrak yang diharapkan oleh kode lain, Anda baru saja membuat bug yang sangat jahat (jika tidak ada pengujian unit / integrasi, tentu saja).sumber
Tergantung situasinya, jika Anda mencoba menggunakan, kode ini di bawah.
Ekspresi dikonversi ke "OBJECT" dan mengurangi begitu banyak kinerja, tetapi ini masalah tersendiri.
KODE:
Di atas hasil dengan ILSPY.
Jika Anda ingin menjalankan kode ini gunakan kode di bawah ini, dan dapatkan perbedaan waktunya.
Salam
sumber