Pertimbangkan fungsi yang mengembalikan dua nilai. Kita bisa menulis:
// Using out:
string MyFunction(string input, out int count)
// Using Tuple class:
Tuple<string, int> MyFunction(string input)
// Using struct:
MyStruct MyFunction(string input)
Manakah yang merupakan praktik terbaik dan mengapa?
struct
seperti yangEric
disebutkan.Jawaban:
Mereka masing-masing memiliki pro dan kontra.
Parameter keluar cepat dan murah tetapi mengharuskan Anda meneruskan variabel, dan mengandalkan mutasi. Hampir tidak mungkin untuk menggunakan parameter out dengan benar dengan LINQ.
Tuple membuat tekanan pengumpulan sampah dan tidak mendokumentasikan diri sendiri. "Item1" tidak terlalu deskriptif.
Struct kustom bisa lambat untuk disalin jika besar, tetapi mendokumentasikan diri sendiri dan efisien jika kecil. Namun juga merepotkan untuk menentukan sejumlah besar struct kustom untuk penggunaan sepele.
Saya akan cenderung ke solusi struct kustom semua hal lain dianggap sama. Bahkan lebih baik adalah membuat fungsi yang hanya mengembalikan satu nilai . Mengapa Anda mengembalikan dua nilai pada awalnya?
PEMBARUAN: Perhatikan bahwa tupel di C # 7, yang dikirim enam tahun setelah artikel ini ditulis, adalah tipe nilai dan karenanya kecil kemungkinannya untuk menciptakan tekanan pengumpulan.
sumber
Menambah jawaban sebelumnya, C # 7 menghadirkan tupel tipe nilai, tidak seperti
System.Tuple
tipe referensi dan juga menawarkan semantik yang ditingkatkan.Anda masih dapat membiarkannya tanpa nama dan menggunakan
.Item*
sintaks:(string, string, int) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.Item1; //John person.Item2; //Doe person.Item3; //42
Tapi yang benar-benar hebat dari fitur baru ini adalah kemampuannya untuk menamai tuple. Jadi kita bisa menulis ulang seperti ini:
(string FirstName, string LastName, int Age) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.FirstName; //John person.LastName; //Doe person.Age; //42
Destrukturisasi juga didukung:
(string firstName, string lastName, int age) = getPerson()
sumber
Saya pikir jawabannya tergantung pada semantik dari apa yang dilakukan fungsi tersebut, dan hubungan antara kedua nilai tersebut.
Misalnya,
TryParse
metode mengambilout
parameter untuk menerima nilai parsing, dan mengembalikan abool
untuk menunjukkan apakah parse berhasil atau tidak. Kedua nilai tidak benar-benar dimiliki bersama, jadi, secara semantik, ini lebih masuk akal, dan maksud kode lebih mudah dibaca, untuk menggunakanout
parameter.Namun, jika fungsi Anda mengembalikan koordinat X / Y dari beberapa objek di layar, maka kedua nilai tersebut secara semantik menjadi satu dan akan lebih baik menggunakan a
struct
.Saya pribadi menghindari penggunaan a
tuple
untuk apa pun yang akan terlihat oleh kode eksternal karena sintaks yang canggung untuk mengambil anggota.sumber
out
parameternull
. Ada beberapa jenis yang tidak dapat diubah di luar sana.try
pola yang bekerja dengan antarmuka kovarian adalahT TryGetValue(whatever, out bool success)
; Pendekatan itu akan memungkinkan antarmukaIReadableMap<in TKey, out TValue> : IReadableMap<out TValue>
, dan membiarkan kode yang ingin memetakan instanceAnimal
ke instanceCar
untuk menerimaDictionary<Cat, ToyotaCar>
penggunaanTryGetValue<TKey>(TKey key, out bool success)
. Varians seperti itu tidak dimungkinkan jikaTValue
digunakan sebagairef
parameter.Saya akan pergi dengan pendekatan menggunakan parameter Out karena dalam pendekatan kedua Anda akan perlu membuat dan objek kelas Tuple dan kemudian menambah nilai, yang menurut saya merupakan operasi yang mahal dibandingkan dengan mengembalikan nilai parameter keluar. Meskipun jika Anda ingin mengembalikan beberapa nilai di Tuple Class (yang tidak dapat dicapai hanya dengan mengembalikan satu parameter keluar) maka saya akan menggunakan pendekatan kedua.
sumber
out
. Selain itu, adaparams
kata kunci yang tidak saya sebutkan untuk menjaga pertanyaan tetap lurus.Anda tidak menyebutkan satu opsi lagi, yaitu memiliki kelas khusus, bukan struct. Jika data memiliki semantik yang terkait dengannya yang dapat dioperasikan oleh fungsi, atau ukuran instance cukup besar (> 16 byte sebagai aturan praktis), kelas khusus mungkin lebih disukai. Penggunaan "keluar" tidak direkomendasikan dalam API publik karena hubungannya dengan pointer dan membutuhkan pemahaman tentang cara kerja jenis referensi.
https://msdn.microsoft.com/en-us/library/ms182131.aspx
Tuple bagus untuk penggunaan internal, tetapi penggunaannya canggung di API publik. Jadi, pilihan saya adalah antara struct dan class untuk API publik.
sumber
Tidak ada "praktik terbaik". Ini adalah apa yang membuat Anda nyaman dan apa yang paling berhasil dalam situasi Anda. Selama Anda konsisten dengan ini, tidak ada masalah dengan solusi apa pun yang Anda posting.
sumber