Jika kita ingin mendapatkan nilai dari suatu metode, kita bisa menggunakan nilai balik, seperti ini:
public int GetValue();
atau:
public void GetValue(out int x);
Saya tidak begitu mengerti perbedaan di antara mereka, jadi, saya tidak tahu mana yang lebih baik. Bisakah Anda jelaskan ini?
Terima kasih.
Tuple
jika Anda mau, tetapi konsensus umum adalah bahwa jika Anda perlu mengembalikan lebih dari satu hal, hal-hal tersebut biasanya terkait entah bagaimana dan hubungan itu biasanya paling baik dinyatakan sebagai kelas.return Tuple.Create(x, y, z);
bukankah itu jelek. Selain itu, sudah terlambat untuk memperkenalkan mereka di tingkat bahasa. Alasan saya tidak akan membuat kelas untuk mengembalikan nilai dari parameter ref / out adalah karena par ref / out hanya benar-benar masuk akal untuk struct yang bisa berubah besar (seperti matriks) atau nilai opsional, dan yang terakhir masih bisa diperdebatkan.Tuple<>
dan C # tuple !. Saya hanya berharap C # diperbolehkan mengembalikan tipe anonim dari metode dengan tipe penyusun kompiler (sepertiauto
di Dlang).Jawaban:
Nilai pengembalian hampir selalu merupakan pilihan yang tepat ketika metode tidak memiliki hal lain untuk dikembalikan. (Faktanya, saya tidak bisa memikirkan kasus mana pun yang saya inginkan metode void dengan
out
parameter, jika saya punya pilihan.Deconstruct
Metode C # 7 untuk dekonstruksi yang didukung bahasa bertindak sebagai pengecualian yang sangat, sangat langka untuk aturan ini .)Selain dari hal lain, itu menghentikan penelepon dari harus mendeklarasikan variabel secara terpisah:
vs.
Nilai-nilai keluar juga mencegah metode chaining seperti ini:
(Memang, itulah salah satu masalah dengan setter properti juga, dan itulah sebabnya pola pembangun menggunakan metode yang mengembalikan pembangun, misalnya
myStringBuilder.Append(xxx).Append(yyy)
.)Selain itu, parameter keluar sedikit lebih sulit untuk digunakan dengan refleksi dan biasanya membuat pengujian lebih sulit juga. (Lebih banyak usaha biasanya dimasukkan ke dalam membuatnya mudah untuk mengejek nilai kembali daripada parameter keluar). Pada dasarnya tidak ada yang dapat saya pikirkan bahwa mereka membuat lebih mudah ...
Mengembalikan nilai FTW.
EDIT: Dalam hal apa yang terjadi ...
Pada dasarnya ketika Anda memberikan argumen untuk parameter "out", Anda harus memasukkan sebuah variabel. (Elemen array juga diklasifikasikan sebagai variabel.) Metode yang Anda panggil tidak memiliki variabel "baru" pada tumpukannya untuk parameter - ia menggunakan variabel Anda untuk penyimpanan. Setiap perubahan dalam variabel langsung terlihat. Berikut ini contoh yang menunjukkan perbedaan:
Hasil:
Perbedaannya ada pada langkah "post" - yaitu setelah variabel atau parameter lokal diubah. Dalam tes ReturnValue, ini tidak ada bedanya dengan
value
variabel statis . Dalam tes OutParameter,value
variabel diubah oleh garistmp = 10;
sumber
Dictionary.TryGetValue
adalah tidak berlaku di sini, karena itu bukan metode void. Bisakah Anda menjelaskan mengapa Anda menginginkanout
parameter alih - alih nilai balik? (Bahkan untukTryGetValue
, saya lebih suka nilai pengembalian yang berisi semua informasi keluaran, secara pribadi. Lihat NodaTimeParseResult<T>
untuk contoh bagaimana saya mendesainnya.)out
parameter, Anda tidak bisa melakukan apa pun dengan nilai tersebut.Apa yang lebih baik, tergantung pada situasi khusus Anda. Salah satu alasan yang
out
ada adalah untuk memfasilitasi pengembalian beberapa nilai dari satu pemanggilan metode:Jadi satu tidak secara definisi lebih baik dari yang lain. Tetapi biasanya Anda ingin menggunakan pengembalian sederhana, kecuali jika Anda memiliki situasi di atas misalnya.
EDIT: Ini adalah contoh yang menunjukkan salah satu alasan bahwa kata kunci itu ada. Hal di atas sama sekali tidak dianggap sebagai praktik terbaik.
sumber
Anda umumnya harus lebih suka nilai pengembalian daripada param. Keluar params adalah kejahatan yang diperlukan jika Anda menemukan diri Anda menulis kode yang perlu melakukan 2 hal. Contoh yang baik dari ini adalah pola Coba (seperti Int32.TryParse).
Mari kita pertimbangkan apa yang harus dilakukan oleh penelepon dari dua metode Anda. Sebagai contoh pertama saya bisa menulis ini ...
Perhatikan bahwa saya dapat mendeklarasikan variabel dan menetapkannya melalui metode Anda dalam satu baris. Untuk contoh ke-2 terlihat seperti ini ...
Saya sekarang terpaksa mendeklarasikan variabel saya di muka dan menulis kode saya melalui dua baris.
memperbarui
Tempat yang tepat untuk melihat ketika mengajukan pertanyaan semacam ini adalah .NET Framework Design Guidelines. Jika Anda memiliki versi bukunya maka Anda dapat melihat anotasi dari Anders Hejlsberg dan lainnya tentang hal ini (halaman 184-185) tetapi versi online ada di sini ...
http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx
Jika Anda menemukan diri Anda perlu mengembalikan dua hal dari API maka membungkusnya dalam struct / kelas akan lebih baik daripada param.
sumber
Ada satu alasan untuk menggunakan
out
param yang belum disebutkan: metode panggilan wajib menerimanya. Jika metode Anda menghasilkan nilai yang tidak boleh dibuang oleh penelepon, menjadikannyaout
memaksa penelepon untuk menerimanya secara khusus:Tentu saja penelepon masih dapat mengabaikan nilai dalam sebuah
out
param, tetapi Anda telah meminta perhatian mereka untuk itu.Ini adalah kebutuhan yang langka; lebih sering, Anda harus menggunakan pengecualian untuk masalah asli atau mengembalikan objek dengan informasi status untuk "FYI", tetapi mungkin ada keadaan di mana ini penting.
sumber
Itu preferensi terutama
Saya lebih suka pengembalian dan jika Anda memiliki banyak pengembalian, Anda dapat membungkusnya dalam DTO Hasil
sumber
Anda hanya dapat memiliki satu nilai kembali sedangkan Anda dapat memiliki beberapa parameter keluar.
Anda hanya perlu mempertimbangkan parameter dalam kasus tersebut.
Namun, jika Anda perlu mengembalikan lebih dari satu parameter dari metode Anda, Anda mungkin ingin melihat apa yang Anda kembali dari pendekatan OO dan mempertimbangkan apakah Anda lebih baik mengembalikan objek atau struct dengan parameter ini. Karenanya Anda kembali ke nilai pengembalian lagi.
sumber
Anda hampir selalu harus menggunakan nilai kembali. '
out
' Parameter membuat sedikit gesekan ke banyak API, komposisi, dll.Pengecualian yang paling penting yang muncul dalam pikiran adalah ketika Anda ingin mengembalikan beberapa nilai (.Net Framework tidak memiliki tupel hingga 4.0), seperti dengan
TryParse
pola.sumber
Saya lebih suka yang berikut daripada yang ada dalam contoh sederhana ini.
Tapi, semuanya sama saja. Biasanya, seseorang hanya akan menggunakan 'keluar' jika mereka perlu melewati beberapa nilai kembali dari metode. Jika Anda ingin mengirim nilai masuk dan keluar dari metode, orang akan memilih 'ref'. Metode saya adalah yang terbaik, jika Anda hanya mengembalikan nilai, tetapi jika Anda ingin melewatkan parameter dan mendapatkan nilai kembali, salah satu kemungkinan akan memilih pilihan pertama Anda.
sumber
Saya pikir salah satu dari beberapa skenario di mana itu akan berguna ketika bekerja dengan memori yang tidak dikelola, dan Anda ingin membuatnya jelas bahwa nilai "yang dikembalikan" harus dibuang secara manual, daripada mengharapkannya akan dibuang dengan sendirinya .
sumber
Selain itu, nilai kembali kompatibel dengan paradigma desain asinkron.
Anda tidak dapat menetapkan fungsi "async" jika menggunakan parameter ref atau out.
Singkatnya, Nilai Pengembalian memungkinkan metode chaining, sintaks yang lebih bersih (dengan menghilangkan keharusan bagi pemanggil untuk mendeklarasikan variabel tambahan), dan memungkinkan desain asinkron tanpa perlu modifikasi substansial di masa depan.
sumber
Keduanya memiliki tujuan yang berbeda dan tidak diperlakukan sama oleh kompiler. Jika metode Anda perlu mengembalikan nilai, maka Anda harus menggunakan pengembalian. Out digunakan di mana metode Anda perlu mengembalikan beberapa nilai.
Jika Anda menggunakan kembali, maka data pertama kali ditulis ke tumpukan metode dan kemudian di metode panggilan. Sementara dalam kasus keluar, itu langsung ditulis ke tumpukan metode panggilan. Tidak yakin apakah ada perbedaan lagi.
sumber
Seperti yang orang lain katakan: nilai balik, bukan parameter.
Bolehkah saya merekomendasikan kepada Anda buku "Pedoman Desain Kerangka Kerja" (edisi kedua)? Halaman 184-185 membahas alasan menghindari params. Seluruh buku akan mengarahkan Anda ke arah yang benar pada semua jenis masalah .NET coding.
Sekutu dengan Kerangka Desain Pedoman adalah penggunaan alat analisis statis, FxCop. Anda akan menemukan ini di situs Microsoft sebagai unduhan gratis. Jalankan ini pada kode kompilasi Anda dan lihat apa yang dikatakannya. Jika itu mengeluh tentang ratusan dan ratusan hal ... jangan panik! Lihatlah dengan tenang dan hati-hati pada apa yang dikatakan tentang setiap kasus. Jangan terburu-buru memperbaiki hal-hal secepatnya. Belajarlah dari apa yang dikatakannya kepada Anda. Anda akan ditempatkan di jalan menuju penguasaan.
sumber
Menggunakan kata kunci keluar dengan tipe pengembalian bool, terkadang dapat mengurangi kode mengasapi dan meningkatkan keterbacaan. (Terutama ketika info tambahan di param sering diabaikan). Misalnya:
vs:
sumber
Tidak ada perbedaan nyata. Parameter keluar dalam C # untuk memungkinkan metode mengembalikan lebih dari satu nilai, itu saja.
Namun Ada beberapa perbedaan kecil, tetapi tidak ada yang benar-benar penting:
Menggunakan parameter keluar akan memaksa Anda untuk menggunakan dua baris seperti:
saat menggunakan nilai balik akan memungkinkan Anda melakukannya dalam satu baris:
Perbedaan lain (hanya benar untuk tipe nilai dan hanya jika C # tidak inline fungsi) adalah bahwa menggunakan nilai kembali tentu akan membuat salinan nilai ketika fungsi kembali, saat menggunakan parameter OUT tidak harus melakukannya.
sumber
keluar lebih berguna ketika Anda mencoba mengembalikan objek yang Anda nyatakan dalam metode.
Contoh
sumber
nilai kembali adalah nilai normal yang dikembalikan oleh metode Anda.
Dimana sebagai parameter out , well out, dan ref adalah 2 kata kunci dari C # yang diijinkan untuk meneruskan variabel sebagai referensi .
Perbedaan besar antara ref dan keluar adalah, ref harus dijalankan sebelum dan keluar tidak
sumber
Saya curiga saya tidak akan membahas pertanyaan ini, tetapi saya seorang programmer yang sangat berpengalaman, dan saya berharap beberapa pembaca yang lebih berpikiran terbuka akan memperhatikan.
Saya percaya bahwa itu sesuai dengan bahasa pemrograman berorientasi objek lebih baik untuk prosedur pengembalian nilai (VRPs) mereka menjadi deterministik dan murni.
'VRP' adalah nama akademis modern untuk fungsi yang disebut sebagai bagian dari ekspresi, dan memiliki nilai balik yang secara tidak sengaja menggantikan panggilan selama evaluasi ekspresi. Misalnya dalam pernyataan seperti
x = 1 + f(y)
fungsif
berfungsi sebagai VRP.'Deterministik' berarti bahwa hasil fungsi hanya bergantung pada nilai-nilai parameternya. Jika Anda memanggilnya lagi dengan nilai parameter yang sama, Anda yakin untuk mendapatkan hasil yang sama.
'Murni' berarti tidak ada efek samping: memanggil fungsi tidak melakukan apa-apa selain menghitung hasilnya. Ini dapat diartikan sebagai tidak ada efek samping yang penting , dalam praktiknya, jadi jika VRP mengeluarkan pesan debugging setiap kali disebut, misalnya, yang mungkin dapat diabaikan.
Jadi, jika, dalam C #, fungsi Anda tidak deterministik dan murni, saya katakan Anda harus menjadikannya
void
fungsi (dengan kata lain, bukan VRP), dan nilai apa pun yang perlu dikembalikan harus dikembalikan dalam parameterout
atauref
parameter.Misalnya, jika Anda memiliki fungsi untuk menghapus beberapa baris dari tabel database, dan Anda ingin mengembalikan jumlah baris yang dihapus, Anda harus mendeklarasikannya seperti ini:
public void DeleteBasketItems(BasketItemCategory category, out int count);
Jika kadang-kadang Anda ingin memanggil fungsi ini tetapi tidak mendapatkan
count
, Anda selalu dapat menyatakan kelebihan beban.Anda mungkin ingin tahu mengapa gaya ini lebih cocok untuk pemrograman berorientasi objek. Secara umum, itu cocok dengan gaya pemrograman yang bisa (sedikit tidak tepat) disebut 'pemrograman prosedural', dan itu adalah gaya pemrograman prosedural yang lebih cocok pemrograman berorientasi objek.
Mengapa? Model klasik objek adalah bahwa mereka memiliki properti (alias atribut), dan Anda menginterogasi dan memanipulasi objek (terutama) melalui membaca dan memperbarui properti tersebut. Gaya pemrograman prosedural cenderung membuatnya lebih mudah untuk melakukan ini, karena Anda dapat mengeksekusi kode arbitrer di antara operasi yang mendapatkan dan mengatur properti.
Kelemahan dari pemrograman prosedural adalah bahwa, karena Anda dapat mengeksekusi kode arbitrer di semua tempat, Anda bisa mendapatkan beberapa interaksi yang sangat tumpul dan rentan bug melalui variabel global dan efek samping.
Jadi, cukup sederhana, itu adalah praktik yang baik untuk memberi sinyal kepada seseorang yang membaca kode Anda bahwa suatu fungsi dapat memiliki efek samping dengan membuatnya kembali tidak bernilai.
sumber
_
simbol buang untuk mengabaikan parameter keluar, misalnya: DeleteBasketItems (kategori, keluar _);