2012-04-17 45 views
5

Đối với một số lý do tôi đang chiến đấu để thực hiện một tài sản từ một giao diện chung bằng cách sử dụng một lớp cơ sở chung như sau:lớp cơ sở chung kế thừa từ giao diện Generic

public interface IParent<TChild> where TChild : IChild 
{ 
    TChild Child { get; } 
} 

public interface IChild { } 

Sau đó, tôi có một lớp cơ sở:

public class ParentBase<TChild> : IParent<TChild> where TChild : IChild 
{ 
    private TChild _child; 
    public ParentBase(TChild child) 
    { 
     this._child = child; 
    } 
    #region IParent<TChild> Members 

    public TChild Child 
    { 
     get { return _child; } 
    } 

    #endregion 
} 

Bây giờ tôi có một Chánh mới phái sinh và trẻ em đối tượng như sau:

public class MyChild : IChild { } 

public class MyParent : ParentBase<MyChild>, IParent<IChild> 
{ 
    public MyParent(MyChild child) 
     : base(child) 
    { 
    } 
} 

tôi wan t để nhanh chóng nó và nhận được trừu tượng (kiểu giao diện) để vượt qua cho người tiêu dùng như sau:

IParent<IChild> parent = new MyParent(new MyChild()); 

Nhưng đối với một số lý do tôi không thể thực hiện TChild một cách chính xác, mặc dù tôi đã xác định tài sản public TChild Child trên ParentBase, các trình biên dịch nói rằng nó không được thực hiện, ngay cả khi tôi thử thực hiện một cách rõ ràng. Như bạn có thể thấy các ràng buộc là tất cả các cách thức thông qua các lớp cơ sở.

+0

Bạn đang sử dụng phiên bản C# nào? – Oded

+0

Tôi đang sử dụng C# 4 (.NET 4) – Andre

Trả lời

4

Bạn đang phát sinh MyParent từ ParentBase<MyChild>IParent<IChild>. Không có thực hiện cho

IParent<IChild> { IChild Child{get; } } 

Thêm một thực hiện rõ ràng sẽ cho phép mã ban đầu của bạn để biên dịch

public class MyParent : ParentBase<MyChild>, IParent<IChild> 
{ 
    public MyParent(MyChild child) 
     : base(child) 
    { 
    } 

    #region Implementation of IParent<IChild> 

    IChild IParent<IChild>.Child 
    { 
     get { return base.Child; } 
    } 

    #endregion 
} 

Nếu bạn cũng làm IParent hiệp biến như thế này:

public interface IParent<out TChild> where TChild : IChild 
{ 
    TChild Child { get; } 
} 

sau đó bạn có thể bây giờ làm điều này

IParent<IChild> parent = new MyParent(new MyChild()); 

hoặc

ParentBase<MyChild> parent2 = new MyParent(new MyChild()); 

IParent<IChild> parent3 = parent2; 

Và như đã chỉ ra trong câu trả lời của @svick, với hiệp phương sai thì bạn có thể đơn giản hóa bằng cách không phát sinh từ IParent<IChild> và loại bỏ việc thực hiện giao diện rõ ràng.

+0

Người tiêu dùng cần sử dụng IParent và không phải là loại bê tông vì vậy tôi cần một ví dụ về điều này. Và khi họ truy cập vào tài sản con, nó cần phải là IChild – Andre

+0

Bạn cần thực hiện rõ ràng nof IParent .Child – Phil

+0

Nhưng nếu bạn thực hiện 'IParent' covariant và không chỉ định' IParent 'một cách rõ ràng làm cơ sở cho' MyParent ', thì bạn sẽ không phải triển khai 'IParent .Chưa', việc triển khai trong' ParentBase' sẽ đủ. Xem câu trả lời của tôi. – svick

0

Nếu người tiêu dùng cần sử dụng IChild và không phải là TChild, bạn có thể không loại bỏ giao diện chung không?

public interface IParent 
{ 
    public IChild Child { get; } 
} 

và sau đó thừa kế của bạn hoạt động tốt

public class ParentBase<TChild> : IParent where TChild : IChild 
{ 
    public IChild Child { get { return myChild; } } 
} 

public class MyParent : ParentBase<MyChild> // already implements IParent by the base doing so. 
{ 
} 
3

Đây chính là nơi biến chung là hữu ích.Nếu bạn đánh dấu interafce bạn IParent như hiệp biến:

public interface IParent<out TChild> where TChild : IChild 

và loại bỏ nguồn gốc rõ ràng của IParent<IChild> từ MyParent:

public class MyParent : ParentBase<MyChild> 

sau đó MyParent có thể được coi như là nếu nó thực hiện IParent<IChild>. Ví dụ: mã sau sẽ hoạt động:

MyParent parent = new MyParent(new MyChild()); 
IParent<IChild> iParent = parent; 
Các vấn đề liên quan