Ketika merencanakan program saya, saya sering memulai dengan rantai pemikiran seperti:
Tim sepak bola hanyalah daftar pemain sepakbola. Karena itu, saya harus mewakilinya dengan:
var football_team = new List<FootballPlayer>();
Urutan daftar ini mewakili urutan pemain terdaftar dalam daftar.
Tetapi saya menyadari kemudian bahwa tim juga memiliki properti lain, selain daftar pemain semata, yang harus dicatat. Misalnya, total skor berjalan musim ini, anggaran saat ini, warna seragam, a string
mewakili nama tim, dll.
Jadi saya berpikir:
Oke, tim sepak bola seperti daftar pemain, tetapi selain itu, ia memiliki nama (a
string
) dan total skor berjalan (anint
). .NET tidak menyediakan kelas untuk menyimpan tim sepak bola, jadi saya akan membuat kelas sendiri. Struktur yang paling mirip dan relevan saat ini adalahList<FootballPlayer>
, jadi saya akan mewarisi darinya:class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal }
Tetapi ternyata suatu pedoman mengatakan Anda tidak seharusnya mewarisiList<T>
. Saya benar-benar bingung dengan pedoman ini dalam dua hal.
Kenapa tidak?
Tampaknya List
entah bagaimana dioptimalkan untuk kinerja . Bagaimana? Masalah kinerja apa yang akan saya sebabkan jika saya memperpanjang List
? Apa tepatnya yang akan pecah?
Alasan lain yang saya lihat adalah yang List
disediakan oleh Microsoft, dan saya tidak punya kendali atasnya, jadi saya tidak bisa mengubahnya nanti, setelah mengekspos "API publik" . Tetapi saya berjuang untuk memahami hal ini. Apa itu API publik dan mengapa saya harus peduli? Jika proyek saya saat ini tidak dan sepertinya tidak pernah memiliki API publik ini, dapatkah saya dengan aman mengabaikan panduan ini? Jika saya memang mewarisi List
dan ternyata saya memerlukan API publik, kesulitan apa yang akan saya miliki?
Mengapa itu penting? Daftar adalah daftar. Apa yang mungkin bisa berubah? Apa yang mungkin ingin saya ubah?
Dan terakhir, jika Microsoft tidak ingin saya mewarisi List
, mengapa mereka tidak membuat kelas sealed
?
Apa lagi yang harus saya gunakan?
Rupanya, untuk koleksi khusus, Microsoft telah menyediakan Collection
kelas yang seharusnya diperluas List
. Tetapi kelas ini sangat telanjang, dan tidak memiliki banyak hal berguna, sepertiAddRange
misalnya. Jawaban jvitor83 memberikan alasan kinerja untuk metode tertentu, tetapi bagaimana lambat AddRange
tidak lebih baik daripada tidak AddRange
?
Mewarisi dari Collection
jauh lebih banyak pekerjaan daripada mewarisi List
, dan saya tidak melihat manfaatnya. Tentunya Microsoft tidak akan mengatakan kepada saya untuk melakukan pekerjaan ekstra tanpa alasan, jadi saya tidak dapat menahan perasaan bahwa saya entah bagaimana salah memahami sesuatu, dan mewarisi Collection
sebenarnya bukanlah solusi yang tepat untuk masalah saya.
Saya telah melihat saran seperti penerapan IList
. Tidak, tidak. Ini adalah puluhan baris kode boilerplate yang tidak menguntungkan saya.
Terakhir, beberapa menyarankan membungkus List
sesuatu:
class FootballTeam
{
public List<FootballPlayer> Players;
}
Ada dua masalah dengan ini:
Itu membuat kode saya verbose tidak perlu. Sekarang saya harus menelepon,
my_team.Players.Count
bukan hanyamy_team.Count
. Untungnya, dengan C # saya dapat mendefinisikan pengindeks untuk membuat pengindeksan transparan, dan meneruskan semua metode internalList
... Tapi itu banyak kode! Apa yang saya dapat untuk semua pekerjaan itu?Itu tidak masuk akal. Tim sepak bola tidak "memiliki" daftar pemain. Ini adalah daftar pemain. Anda tidak mengatakan "John McFootballer telah bergabung dengan pemain SomeTeam". Anda mengatakan "John telah bergabung dengan SomeTeam". Anda tidak menambahkan huruf ke "karakter string", Anda menambahkan huruf ke string. Anda tidak menambahkan buku ke buku perpustakaan, Anda menambahkan buku ke perpustakaan.
Saya menyadari bahwa apa yang terjadi "di bawah tenda" dapat dikatakan sebagai "menambahkan X ke daftar internal Y", tetapi ini sepertinya cara berpikir yang sangat kontra-intuitif tentang dunia.
Pertanyaan saya (dirangkum)
Apa C # cara yang benar mewakili struktur data, yang, "logis" (yang mengatakan, "untuk pikiran manusia") hanya list
dari things
dengan beberapa lonceng dan peluit?
Apakah mewarisi dari List<T>
selalu tidak dapat diterima? Kapan itu bisa diterima? Kenapa / mengapa tidak? Apa yang harus dipertimbangkan oleh seorang programmer, ketika memutuskan apakah akan mewarisi List<T>
atau tidak?
string
diperlukan untuk melakukan semua yang object
dapat dilakukan dan banyak lagi .