2015-09-23 14 views
7

Tôi có một lớp generics với một lớp con cung cấp các loại cụ thể.Bạn có thể phân lớp một lớp generics với một lớp được gõ cụ thể không?

public abstract class GenericBase<T> 
    where T:Interface1 
{ 
} 

tôi phân lớp generics với việc triển khai cụ thể:

public class Customer: 
    GenericBase<Type1> 

(Type1 cụ Interface1).

Tôi có một lớp cơ sở trừu tượng mà có một tài liệu tham khảo như sau:

protected GenericBase<Interface1> genericInstance; 

Cuối cùng, khi tôi cố gắng để gán genericInstance đến một thể hiện của các lớp cơ sở, nó mang lại cho tôi một lỗi biên dịch, nói rằng nó "không thể chuyển đổi hoàn toàn Khách hàng thành GenericBase <Interface1>".

base.genericInstance = new Customer(); //Compiler error 

Tôi không hiểu tại sao tôi sẽ nhận được lỗi này nếu Customer là một subtype của GenericBase<Type1>, và Type1 thực hiện Interface1. Không phải là Customer có hiệu quả là loại GenericBase<Interface1>, nếu đó là một phân lớp của GenericBase<Type1>?

Tôi cho rằng tôi hiểu nhầm về một số thứ về generics ở đây; có cách nào để cho phép hành vi này không?

+0

Không chắc chắn về C#, nhưng điều này chắc chắn không hoạt động trong Java. Trong Java, 'genericInstance' sẽ phải được khai báo là' protected GenericBase genericInstance' (lưu ý: Tôi đã không thử nó để xem nếu nó thực sự hoạt động). – Powerlord

+1

[Hiệp phương sai và Contravariance] (https://msdn.microsoft.com/en-us/library/ee207183) –

+0

Quy tắc của ngón tay cái là generics không phải là biến thể bởi vì bạn không thể nói điều gì sẽ được thực hiện với nó. Tôi không thể gán một 'List ' vào một 'List ' vì nếu không, tôi có thể thêm một 'Dog' vào' List 'mặc dù nó thực sự là một' List ' – Powerlord

Trả lời

9

Trong C#, hiệp phương sai (gán một kiểu dẫn xuất cho kiểu cơ sở) không thể áp dụng cho các lớp chung. Kết quả là, bạn sẽ cần phải áp dụng một giao diện được đánh dấu cụ thể là covariant, sử dụng out parameter modifier trên giao diện IGenericBase mới.

protected IGenericBase<Interface1> genericInstance = new Customer(); 

public interface IGenericBase<out T> {} 

public abstract class GenericBase<T> : IGenericBase<T> 
    where T:Interface1 {} 

public interface Interface1 {} 

public class Type1 : Interface1 {} 

public class Customer: GenericBase<Type1> {} 
+2

Tôi biết C# có các toán tử tương tự cú pháp kỳ lạ '' và '' của Java, tôi không biết chúng là '' và ''. – Powerlord

+0

Tôi không thể sử dụng giao diện covariant vì các loại của tôi đang được sử dụng làm giá trị trả lại và tham số đầu vào trong giao diện của tôi. Nhưng ít nhất bây giờ tôi hiểu một chút về hiệp phương sai; một cái gì đó tôi đã không xử lý trước đây. – GendoIkari

4

C# không có hiệp phương sai của các lớp chung, về cơ bản có nghĩa là bạn không thể gán giá trị với một đối số kiểu có nguồn gốc hơn cho biến với đối số kiểu có nguồn gốc ít hơn.

Điều đó sẽ làm việc với giao diện, mặc dù, với một số điều kiện, nếu kiểu tham số chỉ được sử dụng trong các vị trí biến đổi, tức là kiểu trả về của phương thức và thuộc tính.

Tham khảo this và các bit tài liệu khác để biết thêm thông tin.

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