2015-04-23 14 views
6

Giả sử tôi muốn có một lớp chung Box có thể chứa nội dung nào đó bên trong, vì vậy, đó là Box<T>. Box<T> có một phương pháp Transform mà trả về một Box<U>:Các kiểu mẫu kỳ lạ định kỳ với các loại chung bổ sung

public Box<U> Transform<U>(Func<T, U> transform) 

Cho đến nay điều này đã được khá đơn giản. Tuy nhiên, tôi thực sự cần một trừu tượng Box, vì cách các giá trị được đóng hộp và chuyển đổi được thực hiện cụ thể. (Tôi không thể có một giao diện vì có các phương thức khác được triển khai thông qua thành phần của các phương thức trừu tượng, nhưng điều này không thay đổi bất cứ thứ gì).

Tất nhiên, tôi muốn tôi ghi đè các phương thức Transform để trả lại một lớp con thích hợp của Box, chứ không phải là Box. Kể từ khi loại trở lại của phương pháp trọng là bất biến trong C#, tôi chuyển sang curiously recurring template pattern (xem IComparable<T>):

public abstract class Box<B, T> where B : Box<B, T> 

Bây giờ mỗi lớp tôi kế thừa từ Box<B, T> nên tham khảo bản thân hoặc toàn phá vỡ địa ngục mất:

public class FooBox<T> : Box<FooBox, T> 

Tuy nhiên, điều này hoàn toàn phá hủy các Transform phương pháp:

public abstract Box<B, U> Transform<U>(Func<T, U> transform); 

thất bại trong việc biên dịch với The type 'B' cannot be used as type parameter 'B' in the generic type or method 'Test.Box<B,T>'. There is no implicit reference conversion from 'B' to 'Test.Box<B,U>'. (CS0311). Điều đó có ý nghĩa, vì kiểu trả về bây giờ là Box<B, U> và B là Box<B, T>, không phải là Box<B, U>.

Việc sửa chữa đơn giản sẽ không làm việc:

public abstract Box<B, U> Transform<U>(Func<T, U> transform) where B : Box<B, U>; 

thất bại trong việc biên dịch với 'Test.Box<B,T>.Transform<U>()' does not define type parameter 'B' (CS0699).

Có cách nào để giải quyết vấn đề này hay tôi thực sự vẽ mình vào một góc?

+0

có thể bạn chỉ cần làm cho nó một 'Hộp 'và chuyển thông tin thực hiện cụ thể trong thông qua các phương pháp nhà máy? –

+0

@MillieSmith loại bỏ CRTP sẽ hoạt động, tất nhiên, nhưng điều đó sẽ dẫn đến việc không thể kiểm soát các phương thức đó như 'Hộp Kết hợp (Hộp khác, Func merge)' thực sự chấp nhận 'Hộp' tương thích. – Alexey

Trả lời

1

Tôi nghĩ rằng vấn đề với sửa lỗi thẳng là sử dụng lại thông số loại B. Hãy thử một cái gì đó khác, và bao gồm nó như là một tham số kiểu:

public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) where B2 : Box<B2, U>; 

Cập nhật: bạn đã nêu:

bây giờ tôi không thể đảm bảo B2 đó và B thực sự là những lớp có nguồn gốc tương tự, đó là mục tiêu của tôi

Đây không phải là trường hợp mặc dù, B2 không (có thể không?) kế thừa từ B, U có thể kế thừa T nếu bạn muốn. Bạn có thể bao gồm điều đó như một ràng buộc. Đó là không cần thiết cho mô hình mặc dù, kể từ khi lên đến cơ thể của Transform để sắp xếp nó ra.

ví dụ:

public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) 
    where B2 : Box<B2, U> 
    where U : T 
+0

Không 100% bạn cần 'B2' thay vì' B', nhưng bạn chắc chắn cần nó như một tham số kiểu cho 'Biến đổi ' –

+0

Biên dịch đó (nếu tôi thêm B2 vào các tham số chung của phương thức), nhưng bây giờ tôi không thể đảm bảo rằng B2 và B thực sự là cùng một lớp dẫn xuất, đó là mục tiêu của tôi. – Alexey

+0

câu trả lời cập nhật. –

Các vấn đề liên quan