Apakah menggunakan .NET 4.0 Tuples dalam kode C # saya adalah Keputusan Desain yang Buruk?

166

Dengan tambahan kelas Tuple di .net 4, saya telah mencoba memutuskan apakah menggunakannya dalam desain saya adalah pilihan yang buruk atau tidak. Cara saya melihatnya, Tuple bisa menjadi jalan pintas untuk menulis kelas hasil (saya yakin ada kegunaan lain juga).

Jadi ini:

public class ResultType
{
    public string StringValue { get; set; }
    public int IntValue { get; set; }
}

public ResultType GetAClassedValue()
{
    //..Do Some Stuff
    ResultType result = new ResultType { StringValue = "A String", IntValue = 2 };
    return result;
}

Setara dengan ini:

public Tuple<string, int> GetATupledValue()
{
    //...Do Some stuff
    Tuple<string, int> result = new Tuple<string, int>("A String", 2);
    return result;
}

Jadi mengesampingkan kemungkinan bahwa saya kehilangan titik Tuples, apakah contoh dengan Tuple pilihan desain yang buruk? Bagi saya sepertinya kurang berantakan, tetapi tidak mendokumentasikan dan membersihkan diri. Berarti dengan tipe tersebut ResultType, sangat jelas nanti tentang apa arti setiap bagian dari kelas tetapi Anda memiliki kode tambahan untuk dipelihara. Dengan itu Tuple<string, int>Anda harus mencari dan mencari tahu apa yang masing-masing Itemwakili, tetapi Anda menulis dan mempertahankan lebih sedikit kode.

Pengalaman apa pun yang Anda miliki dengan pilihan ini akan sangat dihargai.

Jason Webb
sumber
16
@Boltbait: karena tuple berasal dari teori himpunan en.wikipedia.org/wiki/Tuple
Matthew Whited
16
@BoltBait: "tuple" adalah seperangkat nilai yang diurutkan, dan tidak harus ada hubungannya dengan baris dalam database.
FrustratedWithFormsDesigner
19
Tuples di c # akan lebih baik jika ada beberapa tindakan membongkar tuple yang baik :)
Justin
4
@ John Saunders Pertanyaan saya secara khusus tentang keputusan desain di c #. Saya tidak menggunakan bahasa .net lainnya, jadi saya tidak yakin bagaimana tuple memengaruhi mereka. Jadi saya menandainya c #. Tampaknya masuk akal bagi saya tetapi perubahan ke. Net juga baik-baik saja kurasa.
Jason Webb
13
@ John Saunders: Saya cukup yakin dia bertanya tentang keputusan desain yang berkaitan dengan menggunakan atau tidak menggunakan Tuples dalam aplikasi yang ditulis murni dalam C #. Saya tidak percaya dia bertanya tentang keputusan desain yang digunakan untuk membuat bahasa C #.
Brett Widmeier

Jawaban:

163

Tuples sangat bagus jika Anda mengontrol keduanya membuat dan menggunakannya - Anda dapat mempertahankan konteks, yang penting untuk memahaminya.

Namun, pada API publik, mereka kurang efektif. Konsumen (bukan Anda) harus menebak atau mencari dokumentasi, terutama untuk hal-hal seperti Tuple<int, int>.

Saya akan menggunakannya untuk anggota pribadi / internal, tetapi menggunakan kelas hasil untuk anggota publik / yang dilindungi.

Jawaban ini juga memiliki beberapa info.

Bryan Watts
sumber
19
Perbedaan antara publik / pribadi sangat penting, terima kasih telah mengangkatnya. Mengembalikan tupel di API publik Anda adalah ide yang sangat buruk, tetapi secara internal di mana segala sesuatunya dapat digabungkan dengan erat (tapi tidak apa - apa ) tidak apa-apa.
Clinton Pierce
36
Digabungkan erat, atau tergabung rapat? ;)
contactmatt
Tidak dapatkah dokumentasi yang sesuai berguna di sini? Sebagai contoh, Scala's StringOps(pada dasarnya kelas "metode ekstensi" untuk Java String) memiliki metode parition(Char => Boolean): (String, String)(mengambil predikat, mengembalikan tuple dari 2 string). Sudah jelas apa outputnya (jelas yang akan menjadi karakter yang predikatnya benar dan yang lain yang salah, tetapi tidak jelas yang mana). Dokumentasinya yang menjelaskan hal ini (dan pencocokan pola dapat digunakan untuk memperjelas dalam penggunaan yang mana).
Kat
@ Mike: Itu membuatnya sulit untuk mendapatkan yang benar dan yang mudah salah, ciri khas dari API yang akan menyebabkan rasa sakit bagi seseorang di suatu tempat :-)
Bryan Watts
79

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 outparameter 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 varkata kunci untuk membiarkan kompiler 'menyimpulkan' jenis untuk Anda. Inilah versi itu:

var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
   // use foundItem...
}
LBushkin
sumber
5
@stakx: Ya, saya setuju. Tetapi perlu diingat - contoh ini sebagian besar dimaksudkan untuk menggambarkan kasus ketika penggunaan a Tuple<> bisa masuk akal. Selalu ada alternatif ...
LBushkin
1
Saya pikir mengganti parameter dengan Tuple, seperti pada TryGetValue atau TryParse, adalah salah satu dari beberapa kasus di mana masuk akal jika API publik mengembalikan Tuple. Bahkan, setidaknya satu bahasa .NET secara otomatis membuat API ini berubah untuk Anda.
Joel Mueller
1
@stakx: Tuple juga tidak berubah, sedangkan array tidak.
Robert Paulson
2
Saya mengerti bahwa Tuples hanya berguna sebagai objek pemain poker yang tidak berubah.
Gennady Vanin Геннадий Ванин
2
+1 Jawaban yang bagus - Saya suka dua contoh awal Anda yang sebenarnya sedikit mengubah pikiran saya. Saya tidak pernah melihat contoh sebelumnya di mana sebuah tuple setidaknya sebanyak yang sesuai dengan struct atau jenis kustom. Namun, "contoh kehidupan nyata" terakhir Anda bagi saya tampaknya tidak menambah banyak nilai lagi. Dua contoh pertama sempurna dan sederhana. Yang terakhir agak sulit untuk dipahami dan jenis "PS" Anda menjadikannya tidak berguna karena pendekatan alternatif Anda jauh lebih sederhana dan tidak memerlukan tupel.
chiccodoro
18

Tuples bisa bermanfaat ... tetapi nantinya bisa menjadi sakit. Jika Anda memiliki metode yang mengembalikan Tuple<int,string,string,int>bagaimana Anda tahu apa nilai-nilai itu nantinya. Apakah mereka ID, FirstName, LastName, Ageatau tidak UnitNumber, Street, City, ZipCode.

Matthew Whited
sumber
9

Tuples adalah tambahan yang cukup underwhelming untuk CLR dari perspektif programmer C #. Jika Anda memiliki koleksi item yang panjangnya bervariasi, Anda tidak perlu mereka memiliki nama statis yang unik pada waktu kompilasi.

Tetapi jika Anda memiliki koleksi panjang konstan, ini menyiratkan bahwa tetap lokasi dalam koleksi masing-masing memiliki makna yang telah ditentukan sebelumnya. Dan itu selalu lebih baik untuk memberi mereka nama-nama statis yang tepat dalam kasus itu, daripada harus mengingat pentingnya Item1, Item2dll

Kelas anonim di C # sudah memberikan solusi luar biasa untuk penggunaan pribadi paling umum dari tupel, dan mereka memberikan nama yang bermakna untuk item tersebut, sehingga mereka sebenarnya lebih unggul dalam hal itu. Satu-satunya masalah adalah mereka tidak bisa keluar dari metode yang disebutkan. Saya lebih suka melihat bahwa pembatasan dicabut (mungkin hanya untuk metode pribadi) daripada memiliki dukungan khusus untuk tupel dalam C #:

private var GetDesserts()
{
    return _icecreams.Select(
        i => new { icecream = i, topping = new Topping(i) }
    );
}

public void Eat()
{
    foreach (var dessert in GetDesserts())
    {
        dessert.icecream.AddTopping(dessert.topping);
        dessert.Eat();
    }
}
Daniel Earwicker
sumber
Sebagai fitur umum, apa yang ingin saya lihat adalah untuk .net untuk menentukan standar untuk beberapa jenis khusus jenis anonim, sehingga misalnya struct var SimpleStruct {int x, int y;}akan mendefinisikan sebuah struct dengan nama yang dimulai dengan panduan yang terkait dengan struct sederhana dan memiliki sesuatu seperti {System.Int16 x}{System.Int16 y}ditambahkan; nama apa pun yang dimulai dengan GUID itu akan diminta untuk mewakili suatu struct yang hanya mengandung elemen-elemen dan konten tertentu yang ditentukan; jika beberapa definisi untuk nama yang sama berada dalam ruang lingkup dan mereka cocok, semua akan dianggap tipe yang sama.
supercat
Hal semacam itu akan sangat membantu untuk beberapa jenis tipe, termasuk kelas dan struktur yang bisa berubah dan tidak berubah serta antarmuka dan delegasi untuk digunakan dalam situasi di mana struktur yang cocok harus dianggap menyiratkan semantik yang cocok. Walaupun pasti ada alasan mengapa mungkin berguna untuk memiliki dua tipe delegasi yang memiliki parameter yang sama tidak dianggap dapat dipertukarkan, juga akan membantu jika seseorang dapat menentukan bahwa suatu metode menginginkan delegasi yang mengambil kombinasi beberapa parameter tetapi di luar itu tidak tidak peduli delegasi macam apa itu.
supercat
Sangat disayangkan bahwa jika dua orang yang berbeda ingin menulis fungsi yang mengambil sebagai delegasi input yang memerlukan refparameter tunggal , satu-satunya cara adalah mungkin untuk memiliki satu delegasi yang dapat diteruskan ke kedua fungsi adalah jika satu orang menghasilkan dan mengkompilasi sebuah jenis delegasi dan memberikannya kepada yang lain untuk membangun melawan. Tidak mungkin kedua orang dapat menunjukkan bahwa kedua jenis ini harus dianggap sama.
supercat
Apakah Anda memiliki contoh konkret tentang di mana Anda akan menggunakan kelas anonim Tuple? Saya baru saja menelusuri 50 tempat di basis kode saya di mana saya menggunakan tuple, dan semuanya adalah nilai pengembalian (biasanya yield return) atau merupakan elemen koleksi yang digunakan di tempat lain, jadi jangan gunakan kelas anonim.
2
@JonofAllTrades - pendapat mungkin berbeda-beda, tetapi saya mencoba merancang metode publik seolah-olah mereka akan digunakan oleh orang lain, bahkan jika seseorang itu adalah saya, jadi saya memberikan layanan pelanggan yang baik untuk diri saya sendiri! Anda cenderung memanggil fungsi lebih dari yang Anda tulis. :)
Daniel Earwicker
8

Mirip dengan kata kunci var, ini dimaksudkan sebagai kenyamanan - tetapi juga mudah disalahgunakan.

Menurut pendapat saya yang paling sederhana, jangan mengekspos Tuplesebagai kelas kembali. Gunakan secara pribadi, jika layanan atau struktur data komponen memerlukannya, tetapi kembalikan kelas-kelas terkenal yang terbentuk dari metode publik.

// one possible use of tuple within a private context. would never
// return an opaque non-descript instance as a result, but useful
// when scope is known [ie private] and implementation intimacy is
// expected
public class WorkflowHost
{
    // a map of uri's to a workflow service definition 
    // and workflow service instance. By convention, first
    // element of tuple is definition, second element is
    // instance
    private Dictionary<Uri, Tuple<WorkflowService, WorkflowServiceHost>> _map = 
        new Dictionary<Uri, Tuple<WorkflowService, WorkflowServiceHost>> ();
}
johnny g
sumber
2
Bahasa Mainstream "RAD" (Java adalah contoh terbaik) selalu memilih keamanan dan menghindari menembak diri sendiri dalam skenario jenis kaki. Saya senang Microsoft mengambil risiko dengan C # dan memberikan bahasa tersebut kekuatan yang bagus, bahkan jika itu dapat disalahgunakan.
Matt Greer
4
Kata kunci var tidak mungkin disalahgunakan. Mungkin maksudmu dinamis?
Chris Marisic
@ Chris Marisic, hanya untuk mengklarifikasi saya tidak bermaksud dalam skenario yang sama - Anda benar-benar benar, vartidak dapat dikembalikan atau ada di luar ruang lingkup yang dinyatakan. namun, masih memungkinkan untuk menggunakannya melebihi tujuan yang dimaksudkan dan "disalahgunakan"
johnny g
5
Saya masih berdiri pada periode var yang tidak bisa disalahgunakan. Ini hanyalah kata kunci untuk membuat definisi variabel lebih pendek. Argumen Anda mungkin tentang jenis anonim, tetapi bahkan yang benar-benar tidak dapat disalahgunakan karena mereka masih normal terkait jenis statis sekarang dinamis adalah cerita yang sangat berbeda.
Chris Marisic
4
var dapat disalahgunakan dalam arti bahwa jika digunakan secara berlebihan terkadang dapat menyebabkan masalah bagi orang yang membaca kode. Terutama jika Anda tidak di Visual Studio dan kurang cerdas.
Matt Greer
5

Menggunakan kelas seperti ResultTypeini lebih jelas. Anda dapat memberikan nama yang bermakna ke bidang di kelas (sedangkan dengan tupel mereka akan dipanggil Item1dan Item2). Ini bahkan lebih penting jika jenis kedua bidang itu sama: namanya jelas membedakan keduanya.

Richard Fearn
sumber
Satu keuntungan tambahan kecil: Anda dapat dengan aman menyusun ulang parameter untuk suatu kelas. Melakukannya untuk tuple akan memecahkan kode, dan jika bidang memiliki tipe yang sama ini mungkin tidak dapat dideteksi pada waktu kompilasi.
Saya setuju, Tuples digunakan ketika pengembang tidak memiliki energi untuk memikirkan nama kelas yang bermakna yang mengelompokkan nama-nama properti yang bermakna. Pemrograman adalah tentang komunikasi. Tuples adalah antipattern untuk komunikasi. Saya lebih suka Microsoft tidak menggunakan bahasa untuk memaksa pengembang membuat keputusan desain yang bagus.
mike gold
5

Bagaimana kalau menggunakan Tuples dalam pola hiasi-semacam-tidak-dekorasi? (Transformasi Schwartzian untuk orang Perl). Inilah contoh yang dibuat-buat, untuk memastikan, tetapi Tuples tampaknya menjadi cara yang baik untuk menangani hal semacam ini:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] files = Directory.GetFiles("C:\\Windows")
                    .Select(x => new Tuple<string, string>(x, FirstLine(x)))
                    .OrderBy(x => x.Item2)
                    .Select(x => x.Item1).ToArray();
        }
        static string FirstLine(string path)
        {
            using (TextReader tr = new StreamReader(
                        File.Open(path, FileMode.Open)))
            {
                return tr.ReadLine();
            }
        }
    }
}

Sekarang, saya bisa menggunakan Object [] dari dua elemen atau dalam contoh khusus ini string [] dari dua elemen. Intinya adalah bahwa saya bisa menggunakan apa pun sebagai elemen kedua dalam Tuple yang digunakan secara internal dan cukup mudah dibaca.

Clinton Pierce
sumber
3
Anda dapat menggunakan Tuple.Create alih-alih konstruktor. Lebih pendek.
Kugel
tipe anonim akan jauh lebih mudah dibaca; seperti halnya menggunakan nama variabel nyata alih-alih 'x'
Dave Cousineau
Itu akan sekarang . Itu masalah SO, jawaban yang diposting bertahun-tahun yang lalu tidak pernah dibersihkan atau diperbarui untuk teknologi baru.
Clinton Pierce
4

IMO "tuple" ini pada dasarnya semua structjenis akses publik anonim dengan anggota yang tidak disebutkan namanya .

Satu- satunya tempat saya akan menggunakan tuple adalah ketika Anda perlu dengan cepat mengumpulkan beberapa data, dalam cakupan yang sangat terbatas. Semantik data harus jelas , sehingga kodenya tidak sulit dibaca. Jadi menggunakan tuple ( int, int) untuk (baris, col) tampaknya masuk akal. Tapi saya sulit sekali menemukan keunggulan dibandingkan structdengan anggota bernama (jadi tidak ada kesalahan dibuat dan baris / kolom tidak sengaja saling dipertukarkan)

Jika Anda mengirim data kembali ke penelepon, atau menerima data dari penelepon, Anda harus benar-benar menggunakan anggota yang structbernama.

Ambil contoh sederhana:

struct Color{ float r,g,b,a ; }
public void setColor( Color color )
{
}

Versi tuple

public void setColor( Tuple<float,float,float,float> color )
{
  // why?
}

Saya tidak melihat keuntungan menggunakan tuple di tempat struct dengan anggota bernama. Menggunakan anggota yang tidak disebutkan namanya adalah langkah mundur untuk keterbacaan dan pemahaman kode Anda.

Tuple menganggap saya sebagai cara malas untuk menghindari membuat structdengan anggota bernama sebenarnya. Terlalu sering menggunakan tuple, di mana Anda benar-benar merasa Anda / atau orang lain menemukan kode Anda akan membutuhkan anggota bernama A Bad Thing ™ jika saya pernah melihatnya.

bobobobo
sumber
3

Jangan menilai saya, saya bukan ahli, tetapi dengan Tuples baru di C # 7.x sekarang, Anda dapat mengembalikan sesuatu seperti:

return (string Name1, int Name2)

Setidaknya sekarang Anda dapat memberi nama dan pengembang mungkin melihat beberapa informasi.

Denis Gordin
sumber
2

Itu tergantung, tentu saja! Seperti yang Anda katakan, sebuah tuple dapat menghemat kode dan waktu Anda saat Anda ingin mengelompokkan beberapa item bersama untuk konsumsi lokal. Anda juga dapat menggunakannya untuk membuat lebih banyak algoritme pemrosesan generik daripada yang dapat Anda lakukan jika melewati kelas yang konkret. Saya tidak ingat berapa kali saya berharap memiliki sesuatu di luar KeyValuePair atau DataRow untuk dengan cepat melewatkan beberapa tanggal dari satu metode ke metode lainnya.

Di sisi lain, sangat mungkin untuk melakukannya secara berlebihan dan mengedarkan tuple di mana Anda hanya bisa menebak isinya. Jika Anda akan menggunakan tuple lintas kelas, mungkin akan lebih baik untuk membuat satu kelas konkret.

Tentu saja, digunakan dalam jumlah sedang, tupel dapat menghasilkan kode yang lebih ringkas dan mudah dibaca. Anda dapat melihat C ++, STL, dan Boost untuk contoh bagaimana Tuples digunakan dalam bahasa lain, tetapi pada akhirnya, kita semua harus bereksperimen untuk menemukan cara yang paling sesuai dengan lingkungan .NET.

Panagiotis Kanavos
sumber
1

Tuples adalah fitur framework yang tidak berguna di .NET 4. Saya pikir peluang besar terlewatkan dengan C # 4.0. Saya akan senang memiliki tuple dengan anggota bernama, sehingga Anda dapat mengakses berbagai bidang tuple dengan nama, bukan Value1 , Value2 , dll ...

Itu akan membutuhkan perubahan bahasa (sintaks), tetapi itu akan sangat berguna.

Philippe Leybaert
sumber
Bagaimana tuple "fitur bahasa"? Kelasnya tersedia untuk semua bahasa .net bukan?
Jason Webb
11
Relatif tidak berguna untuk C #, mungkin. Tetapi System.Tuple tidak ditambahkan ke kerangka kerja karena C #. Itu ditambahkan untuk memudahkan interoperabilitas antara F # dan bahasa lainnya.
Joel Mueller
@Jason: Saya tidak mengatakan itu adalah fitur bahasa (saya salah ketik, tapi saya memperbaikinya sebelum Anda membuat komentar ini).
Philippe Leybaert
2
@Jason - bahasa dengan dukungan langsung untuk tupel memiliki dukungan implisit untuk mendekonstruksi tupel ke dalam nilai komponennya. Kode yang ditulis dalam bahasa-bahasa tersebut biasanya tidak pernah mengakses properti Item1, Item2. let success, value = MethodThatReturnsATuple()
Joel Mueller
@ Joel: pertanyaan ini ditandai sebagai C #, jadi entah bagaimana tentang C #. Saya masih berpikir mereka bisa mengubahnya menjadi fitur kelas satu dalam bahasa ini.
Philippe Leybaert
1

Saya pribadi tidak akan pernah menggunakan Tuple sebagai tipe pengembalian karena tidak ada indikasi nilai yang diwakilinya. Tuples memiliki beberapa kegunaan yang berharga karena tidak seperti objek mereka adalah tipe nilai dan dengan demikian memahami kesetaraan. Karena ini saya akan menggunakannya sebagai kunci kamus jika saya memerlukan kunci multi bagian atau sebagai kunci untuk klausa GroupBy jika saya ingin mengelompokkan berdasarkan beberapa variabel dan tidak ingin pengelompokan bersarang (Siapa yang ingin pengelompokan bersarang?). Untuk mengatasi masalah dengan verbositas ekstrem, Anda dapat membuatnya dengan metode pembantu. Perlu diingat jika Anda sering mengakses anggota (melalui Item1, Item2, dll) maka Anda mungkin harus menggunakan konstruk yang berbeda seperti struct atau kelas anonim.

Seth Paulson
sumber
0

Saya telah menggunakan tupel, baik yang baru Tuplemaupun yang baru ValueTuple, dalam sejumlah skenario yang berbeda dan sampai pada kesimpulan berikut: jangan gunakan .

Setiap kali, saya mengalami masalah berikut:

  • kode menjadi tidak dapat dibaca karena kurangnya penamaan yang kuat;
  • tidak dapat menggunakan fitur hierarki kelas, seperti DTO kelas dasar dan DTO kelas anak, dll .;
  • jika mereka digunakan di lebih dari satu tempat, Anda akhirnya menyalin dan menempelkan definisi-definisi jelek ini, alih-alih nama kelas yang bersih.

Pendapat saya adalah tuple adalah kerugian, bukan fitur, dari C #.

Saya agak mirip, tetapi kurang kasar, kritik terhadap Func<>dan Action<>. Itu berguna dalam banyak situasi, terutama varian yang sederhana Actiondan Func<type>, tetapi lebih dari itu, saya menemukan bahwa membuat tipe delegasi lebih elegan, mudah dibaca, dapat dipelihara, dan memberi Anda lebih banyak fitur, seperti ref/ outparameter.

Tuan TA
sumber
Saya menyebutkan nama tupel - ValueTuple- dan saya juga tidak menyukainya. Pertama, penamaannya tidak kuat, ini lebih merupakan saran, sangat mudah untuk dikacaukan karena dapat ditetapkan secara implisit ke salah satu Tupleatau ValueTupledengan jumlah dan jenis item yang sama. Kedua, kurangnya pewarisan dan kebutuhan untuk menyalin seluruh definisi dari satu tempat ke tempat lain masih merugikan.
Tn. TA
Saya setuju dengan poin-poin itu. Saya mencoba hanya menggunakan Tuples ketika saya mengontrol produsen dan konsumen, dan jika mereka tidak terlalu "jauh". Artinya, produsen dan konsumen dalam metode yang sama = 'tutup', sedangkan produsen dan konsumen dalam majelis berbeda = 'tahun cahaya jauhnya'. Jadi, jika saya membuat tupel di awal metode, dan menggunakannya di akhir? Tentu, saya baik-baik saja dengan itu. Saya juga mendokumentasikan persyaratan dan semacamnya. Tapi ya, saya setuju bahwa umumnya mereka bukan pilihan yang tepat.
Mike Christiansen