Cara saya melihatnya, Tuple adalah jalan pintas untuk menulis kelas hasil (saya yakin ada kegunaan lain juga).
Memang ada kegunaan lain yang berharga untukTuple<>
- sebagian besar dari mereka melibatkan abstrak semantik kelompok jenis tertentu yang berbagi struktur yang sama, dan memperlakukan mereka hanya sebagai seperangkat nilai yang dipesan. Dalam semua kasus, keuntungan dari tuple adalah mereka menghindari mengacaukan namespace Anda dengan kelas hanya data yang mengekspos properti tetapi bukan metode.
Berikut adalah contoh penggunaan yang masuk akal untuk Tuple<>
:
var opponents = new Tuple<Player,Player>( playerBob, playerSam );
Dalam contoh di atas kami ingin mewakili sepasang lawan, tuple adalah cara yang mudah untuk memasangkan instance ini tanpa harus membuat kelas baru. Ini contoh lain:
var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );
Tangan poker dapat dianggap sebagai hanya satu set kartu - dan tuple (mungkin) cara yang wajar untuk mengekspresikan konsep itu.
mengesampingkan kemungkinan bahwa saya kehilangan titik Tuples, apakah contoh dengan Tuple pilihan desain yang buruk?
Mengembalikan Tuple<>
instance yang sangat diketik sebagai bagian dari API publik untuk tipe publik jarang merupakan ide yang bagus. Seperti yang Anda ketahui sendiri, tuple mengharuskan pihak-pihak yang terlibat (penulis perpustakaan, pengguna perpustakaan) untuk menyetujui sebelumnya mengenai tujuan dan interpretasi jenis tuple yang digunakan. Cukup menantang untuk membuat API yang intuitif dan jelas, menggunakan Tuple<>
secara publik hanya mengaburkan niat dan perilaku API.
Jenis anonim juga merupakan jenis tuple - namun, mereka sangat diketik dan memungkinkan Anda menentukan nama yang jelas dan informatif untuk properti yang termasuk dalam jenis tersebut. Tetapi jenis anonim sulit digunakan di berbagai metode - mereka terutama ditambahkan untuk mendukung teknologi seperti LINQ di mana proyeksi akan menghasilkan jenis yang biasanya kita tidak ingin menetapkan nama. (Ya, saya tahu bahwa tipe anonim dengan tipe dan properti yang sama dikonsolidasikan oleh kompiler).
Aturan praktis saya adalah: jika Anda akan mengembalikannya dari antarmuka publik Anda - jadikan ini tipe yang dinamai .
Aturan praktis saya yang lain untuk menggunakan tuple adalah: argumen metode nama dan variabel tipe localc Tuple<>
sejelas mungkin - membuat nama tersebut mewakili makna hubungan antara elemen tuple. Pikirkan var opponents = ...
contoh saya .
Berikut adalah contoh kasus dunia nyata di mana saya terbiasa Tuple<>
menghindari menyatakan tipe data saja untuk digunakan hanya dalam perakitan saya sendiri . Situasi ini melibatkan fakta bahwa ketika menggunakan kamus umum yang berisi tipe anonim, menjadi sulit untuk menggunakan TryGetValue()
metode untuk menemukan item dalam kamus karena metode ini membutuhkan out
parameter yang tidak dapat disebutkan namanya:
public static class DictionaryExt
{
// helper method that allows compiler to provide type inference
// when attempting to locate optionally existent items in a dictionary
public static Tuple<TValue,bool> Find<TKey,TValue>(
this IDictionary<TKey,TValue> dict, TKey keyToFind )
{
TValue foundValue = default(TValue);
bool wasFound = dict.TryGetValue( keyToFind, out foundValue );
return Tuple.Create( foundValue, wasFound );
}
}
public class Program
{
public static void Main()
{
var people = new[] { new { LastName = "Smith", FirstName = "Joe" },
new { LastName = "Sanders", FirstName = "Bob" } };
var peopleDict = people.ToDictionary( d => d.LastName );
// ??? foundItem <= what type would you put here?
// peopleDict.TryGetValue( "Smith", out ??? );
// so instead, we use our Find() extension:
var result = peopleDict.Find( "Smith" );
if( result.First )
{
Console.WriteLine( result.Second );
}
}
}
PS Ada cara lain (lebih sederhana) untuk mengatasi masalah yang muncul dari jenis anonim dalam kamus, dan itu adalah dengan menggunakan var
kata kunci untuk membiarkan kompiler 'menyimpulkan' jenis untuk Anda. Inilah versi itu:
var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
// use foundItem...
}