我如何在界面中创建两种类型<t,i =“”>继承了两种类型的接口<t,i =“”>

时间:2017-09-11 14:30:27

标签: c# generics types

// 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没有装箱转换或类型参数转换

有一些问题,我正在写续订:

我有一个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

但是,如果我写&#34; T。&#34;,即将到来的BaseEntity字段..

在serviceLayer中,我将调用commentDAL.Save方法:

_commentDAL.Save(...);

如何在commentDAL.Save()

中传递值T class

2 个答案:

答案 0 :(得分: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

由于您明确地使用PageComment内的CommentDALPageComment pc = new PageComment() ...),我会在CommentDAL级别选择没有任何通用参数的设计。

答案 1 :(得分:0)

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

这会失败,因为根据IBaseX<T, I>T被限制为BaseY<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>
{ }