2011-02-03 27 views
9

Tôi nhận được lỗi sau:Tôi có thể triển khai giao diện có chứa thuộc tính thuộc loại con cho giao diện được yêu cầu không?

ClassName.PropertyName cannot implement IClassType.PropertyName because it does not have the matching return type of IBasePropertyType

Bây giờ, đối với các mã:

public class ClassName : IClassType 
{ 
    public IChildPropertyType PropertyName { get; set; } 
} 

public interface IClassType 
{ 
    public IBasePropertyType PropertyName { get; set; } 
} 

public interface IBasePropertyType 
{ 
    // some methods 
} 

public interface IChildPropertyType : IBasePropertyType 
{ 
    // some methods 
} 

Có cách nào để làm những gì tôi đang cố gắng? Tôi biết rằng vấn đề là với co/contravariance, nhưng tôi dường như không thể tìm ra cách để làm điều này.

+0

Vì vậy, câu hỏi là gì? – Victor

+0

@Victor: Có cách nào để triển khai giao diện, nhưng có thuộc tính kiểu con cho loại thuộc tính được xác định trong giao diện không? –

Trả lời

7

Để triển khai giao diện đã cho, bạn phải có cùng loại trả về. Tuy nhiên, có một vài tiềm năng công việc ở quanh để làm cho cuộc sống dễ dàng hơn:

  1. làm cho giao diện của bạn generic
  2. thực hiện giao diện một cách rõ ràng.

Nếu bạn thực hiện IClassType chung chung, như vậy:

public interface IClassType<T> where T : IBasePropertyType 
{ 
    public T PropertyName { get; set; } 
} 

... sau đó bạn có thể thực hiện giao diện này sử dụng các loại tài sản khác nhau:

public class ClassName : IClassType<IChildPropertyType> 
{ 
    public IChildPropertyType PropertyName { get; set; } 
} 

Một lựa chọn khác sẽ rời khỏi bạn giao diện không chung chung, nhưng để có loại cơ sở chung chung triển khai rõ ràng giao diện:

public class ClassBase<T> : IClassType 
    where T : IChildPropertyType 
{ 
    IBasePropertyType IClassType.PropertyName { 
     get {return PropertyName;} 
     set {PropertyName = (IChildPropertyType)value;} 
    } 
    T PropertyName {get;set;} 
} 

Lưu ý rằng tùy chọn cuối cùng này không hoàn toàn lý tưởng vì bạn phải tự động gán thuộc tính cho kiểu con đã cho: trong khi bạn có thể đảm bảo rằng mọi loại IChildProperty là IBasePropertyType, bạn không thể đảm bảo rằng mọi IBasePropertyType là một IChildPropertyType. Tuy nhiên, nếu bạn có thể loại bỏ setter khỏi giao diện ban đầu, hoặc nếu bạn có thể thực hiện các bước khác để đảm bảo rằng setter sẽ không bao giờ được gọi với kiểu sai trong mã của bạn, thì điều này có thể hoạt động.

+0

Tôi đã cố gắng tuyến đường chung, nhưng chưa nhận được tất cả các mảnh với nhau (hoặc người nào khác tôi sẽ không ở đây). Cảm ơn, và tôi mong được nhìn thấy các mẫu mã mà làm cho nó hoạt động. –

+0

@Mark Avenius: Hiện có. Nói cho tôi biết bạn nghĩ gì. – StriplingWarrior

+0

xóa câu trả lời của tôi là của bạn tốt hơn nhiều –

4

Bạn đúng rằng điều này phải làm với hiệp phương sai; cụ thể nó phải làm với phương thức trả về kiểu phương thức ảo, không phải là một loại hiệp phương sai mà ngôn ngữ C# hỗ trợ.

Lưu ý rằng ngay cả khi đã thực hiện, hệ thống bạn mô tả không an toàn. Giả sử chúng ta có:

interface IAnimal {} 
interface IGiraffe : IAnimal {} 
interface ITiger: IAnimal {} 
class Tiger : ITiger {} 
interface IHaveAnAnimal { IAnimal Animal { get; set; } } 
class C : IHaveAnAnimal 
{ 
    public IGiraffe Animal { get; set; } 
} 
... 
IHaveAnAnimal x = new C(); 
x.Animal = new Tiger(); // Uh oh. We just put a Tiger into a property of type IGiraffe. 

Ngay cả khi hiệp phương sai hoàn toàn hợp pháp, loại hiệp phương sai này sẽ không hợp pháp; bạn phải có không có setter để hiệp phương sai hợp pháp.

Giả sử sau đó bạn đã không có setter:

interface IAnimal {} 
interface IGiraffe : IAnimal {} 
interface ITiger: IAnimal {} 
class Tiger : ITiger {} 
interface IHaveAnAnimal { IAnimal Animal { get; } } 
class C : IHaveAnAnimal 
{ 
    public IGiraffe Animal { get; } 
} 

Thật không may này vẫn là không hợp pháp. Nhưng bạn có thể làm điều này:

class C : IHaveAnAnimal 
{ 
    IAnimal IHaveAnAnimal.Animal { get { return this.Animal; } } 
    public IGiraffe Animal { get; } 
} 

Bây giờ khi C được dùng làm C, Animal trả về một con hươu cao cổ và khi được sử dụng IHaveAnAnimal, nó trả về một số thập phân.

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