Khi lên kế hoạch cho các chương trình của mình, tôi thường bắt đầu với một chuỗi những suy nghĩ như vậy:
Một đội bóng chỉ là một danh sách các cầu thủ bóng đá. Vì vậy, tôi nên trình bày nó với:
var football_team = new List<FootballPlayer>();
Thứ tự của danh sách này thể hiện thứ tự mà người chơi được liệt kê trong danh sách.
Nhưng tôi nhận ra rằng các đội cũng có các thuộc tính khác, ngoài danh sách người chơi đơn thuần, phải được ghi lại. Ví dụ: tổng số điểm đang chạy trong mùa này, ngân sách hiện tại, màu đồng nhất, string
đại diện cho tên của đội, v.v.
Vì vậy, sau đó tôi nghĩ:
Được rồi, một đội bóng đá giống như một danh sách các cầu thủ, nhưng ngoài ra, nó có một tên (a
string
) và tổng số điểm (anint
) đang chạy . .NET không cung cấp một lớp để lưu trữ các đội bóng đá, vì vậy tôi sẽ tạo một lớp của riêng mình. Cấu trúc hiện có tương tự và phù hợp nhất làList<FootballPlayer>
, vì vậy tôi sẽ kế thừa từ nó:class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal }
Nhưng nó chỉ ra rằng một hướng dẫn nói rằng bạn không nên thừa kế từList<T>
. Tôi hoàn toàn bối rối bởi hướng dẫn này trong hai khía cạnh.
Tại sao không?
Rõ ràng List
là bằng cách nào đó được tối ưu hóa cho hiệu suất . Làm sao vậy Những vấn đề hiệu suất tôi sẽ gây ra nếu tôi mở rộng List
? Chính xác thì cái gì sẽ phá vỡ?
Một lý do khác mà tôi thấy là List
do Microsoft cung cấp và tôi không có quyền kiểm soát đối với nó, vì vậy tôi không thể thay đổi nó sau này, sau khi tiết lộ "API công khai" . Nhưng tôi đấu tranh để hiểu điều này. API công khai là gì và tại sao tôi nên quan tâm? Nếu dự án hiện tại của tôi không và không có khả năng có API công khai này, tôi có thể bỏ qua hướng dẫn này một cách an toàn không? Nếu tôi thừa kế từ List
và hóa ra tôi cần API công khai, tôi sẽ gặp khó khăn gì?
Tại sao nó thậm chí còn quan trọng? Một danh sách là một danh sách. Điều gì có thể thay đổi? Tôi có thể muốn thay đổi điều gì?
Và cuối cùng, nếu Microsoft không muốn tôi thừa kế List
, tại sao họ không tạo ra lớp học sealed
?
Tôi còn phải sử dụng cái gì nữa?
Rõ ràng, đối với các bộ sưu tập tùy chỉnh, Microsoft đã cung cấp một Collection
lớp nên được mở rộng thay vì List
. Nhưng lớp này rất trống trải và không có nhiều thứ hữu ích, chẳng hạn nhưAddRange
. Câu trả lời của jvitor83 cung cấp một lý do hiệu suất cho phương pháp cụ thể đó, nhưng làm thế nào chậm AddRange
không tốt hơn không AddRange
?
Kế thừa từ Collection
cách làm việc nhiều hơn là kế thừa từ List
, và tôi thấy không có lợi ích gì. Chắc chắn Microsoft sẽ không bảo tôi làm thêm mà không có lý do, vì vậy tôi không thể cảm thấy như mình đang hiểu nhầm điều gì đó và kế thừa Collection
thực sự không phải là giải pháp phù hợp cho vấn đề của tôi.
Tôi đã thấy các đề xuất như thực hiện IList
. Không. Đây là hàng tá dòng mã soạn sẵn mà tôi chẳng thu được gì.
Cuối cùng, một số gợi ý gói List
trong một cái gì đó:
class FootballTeam
{
public List<FootballPlayer> Players;
}
Có hai vấn đề này:
Nó làm cho mã của tôi dài dòng không cần thiết. Bây giờ tôi phải gọi
my_team.Players.Count
thay vì chỉmy_team.Count
. Rất may, với C # tôi có thể định nghĩa các bộ chỉ mục để làm cho việc lập chỉ mục trở nên minh bạch và chuyển tiếp tất cả các phương thức của nội bộList
... Nhưng đó là rất nhiều mã! Tôi nhận được gì cho tất cả công việc đó?Nó chỉ đơn giản là không có ý nghĩa gì. Một đội bóng đá không "có" một danh sách các cầu thủ. Đây là danh sách các cầu thủ. Bạn không nói "John McFootballer đã tham gia với người chơi của someTeam". Bạn nói "John đã tham gia vào một sốTeam". Bạn không thêm chữ cái vào "ký tự của chuỗi", bạn thêm chữ cái vào chuỗi. Bạn không thêm sách vào sách của thư viện, bạn thêm sách vào thư viện.
Tôi nhận ra rằng những gì xảy ra "dưới mui xe" có thể nói là "thêm X vào danh sách nội bộ của Y", nhưng đây có vẻ như là một cách suy nghĩ rất trực quan về thế giới.
Câu hỏi của tôi (tóm tắt)
Cách C # chính xác để biểu diễn một cấu trúc dữ liệu, trong đó, "về mặt logic" (nghĩa là "với tâm trí con người") chỉ là một list
trong things
những tiếng chuông và tiếng huýt sáo?
Là thừa kế từ List<T>
luôn luôn không thể chấp nhận? Khi nào nó được chấp nhận? Tại sao tại sao không? Một lập trình viên phải xem xét điều gì, khi quyết định có nên thừa kế từ List<T>
hay không?
string
là cần thiết để làm mọi thứ object
có thể làm và nhiều hơn nữa .