2017-09-11 48 views
0
// T => a class 
// I => Guid, int etc.. 

public interface IBaseX<T, I> 
     where T : BaseY<I> {..} 
public class BaseX<T, I> : IBaseX<T, I> 
     where T : BaseY<I> {..} 

// it works but, 

public interface IMyClass<T, I> 
     where T : IBaseX<T, I> {..} 
public class MyClass<T, I> 
     where T : BaseX<T, I>, IMyClass<T, I> 

// this not works, why not? 

錯誤: 類型T不能被用作在通用類型或方法IBaseX類型參數T。有沒有裝箱轉換或類型參數轉換從T到BaseY我如何在接口<T, I>創建兩種類型的繼承兩種類型的接口<T, I>


有一些問題,我寫更新:

我有一個ORM的項目,包括:

在項目的根目錄: BaseEntity.cs:

public abstract class BaseEntity<T> 
{ 
    public T ID { get; set; } 
    ..... 
} 

內容文件夾: Page.cs:

public class Page : BaseEntity<int> 
{ 
    [MaxLength(250)] 
    [Required] 
    public string Title { get; set; } 
    .... 
} 

PageComment.cs:

public class PageComment : BaseEntity<int> 
{ 
    public int PageID { get; set; } 

    [Required] 
    [MaxLength(500)] 
    public string Body { get; set; } 

    [Required] 
    [MaxLength(175)] 
    public string Email { get; set; } 

    [Required] 
    [MaxLength(150)] 
    public string Title { get; set; } 
    .... 
} 

我有一個數據層的項目,包括:

基本文件夾:

IBaseDAL.cs:

public interface IBaseDAL<T, I> where T : BaseEntity<I> 
{ 
    void Save(T e, string who, WebsiteContext ctx = null); 
    void Update(T e, string who, WebsiteContext ctx = null); 
    void Delete(T e, string who, WebsiteContext ctx = null); 

} 

BaseDAL.cs :

public class BaseDAL<T, I> : IBaseDAL<T, I> where T : BaseEntity<I> 
{ 
    public void Save(T e, string who, WebsiteContext ctx = null) { ... } 
} 

評論文件夾:

ICommentDAL.cs:

public interface ICommentDAL<T> where T : BaseEntity<int>, IBaseDAL<T, int> 
{ 
    int Save(WebsiteContext ctx, NewCommentDTO nc, string who); 
    .... 
} 

CommentDAL.cs:

public class CommentDAL<T> 
    where T : BaseEntity<int>, IBaseDAL<T, int>, ICommentDAL<T> 
{ 
    BaseDAL<T, int> baseDAL = new BaseDAL<T, int>(); 

    public int Save(WebsiteContext ctx, NewCommentDTO<T> nc, string who) 
    { 
     ORM.Content.PageComment pc = new PageComment() 
     { 
      Body = nc.Body, 
      ... 
     }; 
     baseDAL.Save(pc as T, who, ctx); 
    } 
} 

ORM.Content.PageComment類必須爲T

但使用,如果我寫「T.」,來到BaseEntity字段..

在serviceLayer中,我將調用commentDAL.Save方法:

_commentDAL.Save(...);

我如何可以傳遞commentDAL.Save值T級()

+1

所以,你要'''T:BaseX {..}'''或'''T:BaseY {..}'''? – tym32167

+0

基數x中的T需要是基數Y –

+1

通用類型約束沒有「繼承」 - 您必須明確包含您的基類型或接口所需的任何約束。 –

回答

0

見下面的答案,但請注意,您也許應該告訴更多的有關計劃式設計。因爲只編譯一些泛型爲編譯器工作可能不會導致您實際需要的代碼。

以下工作:

public class BaseY<T> 
{ 

} 
public interface IBaseX<T, I> 
     where T : BaseY<I> 
{ 
} 
public class BaseX<T, I> : IBaseX<T, I> 
     where T : BaseY<I> 
{ 
} 

// it works but, 

public interface IMyClass<T, I> 
     where T : BaseY<I>, IBaseX<T, I> 
{ 
} 
public class MyClass<T, I> 
     where T : BaseY<I>, IBaseX<T, I>, IMyClass<T, I> 
{ 
} 

注意,你不能限制T兩個班,所以你不能說where T : BaseY<I>, BaseX<T, I>, IMyClass<T, I>。相反,爲了使構造有意義,BaseXBaseY需要處於繼承層次結構中,並且可以爲更多派生類編寫約束。


考慮更新的結構,我想你應該改變如下:

// from 
public interface ICommentDAL<T> where T : BaseEntity<int>, IBaseDAL<T, int> 
// to 
public interface ICommentDAL<T> : IBaseDAL<T, int> 
    where T : BaseEntity<int> 
// or to 
public interface ICommentDAL : IBaseDAL<PageComment, int> 

因爲這實際上在模型上,而不是在一些DAL類型約束混合創建類型約束的DAL層次結構對模型類無效。

其他定義需要類似的變化:

// from 
public class CommentDAL<T> 
    where T : BaseEntity<int>, IBaseDAL<T, int>, ICommentDAL<T> 
// to 
public class CommentDAL<T> : BaseDAL<T, int>, ICommentDAL<T> 
    where T : BaseEntity<int> 
// or to 
public class CommentDAL : BaseDAL<PageComment, int>, ICommentDAL 

既然你明確地定義與PageCommentCommentDAL反正(PageComment pc = new PageComment() ...),我會選擇設計不會對CommentDAL級別的任何泛型參數工作。因爲根據IBaseX<T, I>T被約束爲BaseY<I>類型的

+0

非常感謝.. @ grek40 [BR] [代碼] 公共接口IMyClass 其中T:BaseY ,IBaseX [代碼] [BR] 但第二並不像你說的.. [BR ] 我無法理解:「相反,爲了讓你的構造具有任何意義,BaseX和BaseY需要處於繼承層次結構中,並且可以爲更多派生類編寫約束。「 –

+0

@MehmetGenç__if__'BaseY '是'class' __and__'T:BaseY ''__and__ T:BaseX '需要('T'來自兩類派生),__then__'BaseX '和'BaseY '必須是同一繼承層次結構的一部分,因爲C#不允許多繼承___,這意味着'BaseY :BaseX '__or__'BaseX :BaseY '必須是真的,所以它們中的一個將會派生得更多(在這兩個層次之間可以有中間類,但必須是另一個的祖先) – grek40

+0

@MehmetGenç看到我的更新 – grek40

0
public interface IMyClass<T, I> 
    where T : IBaseX<T, I> 
{ } 

這將失敗。但是,IMyClass<T, I>的定義沒有此限制,因此不會強制執行T的限制。

注意,傳遞性約束不結轉,你需要再次明確列出它們:

public interface IMyClass<T, I> 
    where T : BaseY<I>, IBaseX<T, I> 
{ } 

同樣的,你還需要指定T約束爲MyClass<T, I>。但是,在這兩個BaseX<T, I>BaseY<I>這兩個都是約束,所以這不起作用,因爲.NET不支持多繼承。你可以儘管使用IBaseX<T, I>接口:

public class MyClass<T, I> 
    where T : BaseY<I>, IBaseX<T, I>, IMyClass<T, I> 
{ } 
相關問題