Hãy xem xét những gì sẽ xảy ra nếu chúng ta đi chệch khỏi ước CRTP bằng cách viết ...
public class Foo : TreeNode<Foo>
{
}
public class Bar : TreeNode<Foo> // parting from convention
{
}
... và sau đó gọi các mã trên như sau:
var foo = new Foo();
var foobar = new Bar();
foobar.AddChild(foo);
Cuộc gọi AddChild
ném một InvalidCastException
nói Unable to cast object of type 'Bar' to type 'Foo'.
Về thành ngữ CRTP - đó là quy ước một mình yêu cầu loại chung phải giống như khai báo ing. Ngôn ngữ phải hỗ trợ các trường hợp khác không tuân theo quy ước CRTP. Eric Lippert đã viết một bài đăng trên blog tuyệt vời về chủ đề này, rằng anh ta đã liên kết với nhau từ crtp via c# answer khác.
Tất cả những gì đã nói, nếu bạn thay đổi việc thực hiện điều này ...
public class TreeNode<T> where T : TreeNode<T>
{
public void AddChild(T a_node)
{
a_node.SetParent(this);
}
void SetParent(TreeNode<T> a_parent)
{
m_parent = a_parent;
}
TreeNode<T> m_parent;
}
... các mã trên mà trước đây ném InvalidCastException
hiện đang làm việc.Thay đổi này làm cho m_Parent
một loại TreeNode<T>
; làm this
một trong hai loại T
như trong Foo
lớp trường hợp hoặc một lớp con của TreeNode<T>
trong trường hợp Bar
lớp từ Bar
thừa hưởng từ TreeNode<Foo>
- một trong hai cách cho phép chúng ta bỏ qua các diễn viên trong SetParent
và thiếu sót mà tránh được những ngoại lệ cast không hợp lệ kể từ khi nhiệm vụ là hợp pháp trong mọi trường hợp. Chi phí thực hiện việc này không còn có thể tự do sử dụng T
ở tất cả các địa điểm như trước đây đã được sử dụng để hy sinh phần lớn giá trị của CRTP.
Một đồng nghiệp/bạn của tôi coi mình là một người mới đến một ngôn ngữ/ngôn ngữ-tính năng cho đến khi anh ta có thể thành thật nói rằng anh ấy "đã sử dụng nó trong giận dữ;" đó là, anh ta biết ngôn ngữ đủ tốt để bị thất vọng rằng không có cách nào để hoàn thành những gì anh ta cần hoặc làm như vậy là đau đớn. Điều này rất tốt có thể là một trong những trường hợp đó, vì có những giới hạn và sự khác biệt ở đây để lặp lại sự thật là generics are not templates.
Tôi cho phép bản thân mình đơn giản hóa ví dụ của bạn. Vui lòng hoàn nguyên nếu bạn không đồng ý. – usr
Thành thật mà nói, điều này trông giống như một headf thông minh ** k. Có gì sai với các cách truyền thống hơn để đại diện cho cây sử dụng bố cục thay thế? Điều này làm bạn mua gì? Tôi hy vọng rằng không có vẻ quá đối kháng. Tôi chỉ tò mò thôi. – spender
@spender phân nửa số lượng phân bổ và giảm số lượng người theo dõi bạn cần tuân theo. Vì vậy, trong mã hiệu suất cao, nó có thể là một sự cân bằng hợp lý. Đối với những cây nhỏ hơn, đó có lẽ là một ý tưởng tồi. – CodesInChaos