【问题标题】:Inheriting generic interfaces with different generic parameters继承具有不同泛型参数的泛型接口
【发布时间】:2014-02-24 17:04:01
【问题描述】:

我不确定这是否只是我没有使用正确的语法,或者我错过了一个概念。

所以基本的设计是这样的:

public abstract class ListItemModelBase
{
    Guid id { get; set; }
}

public abstract class ListModelBase<T> where T : ListItemModelBase
{
    List<T> Items { get; set; }
}

public class OrderListModel : ListModelBase<OrderListItemModel>
{
}

这一切都很好,但现在我想为我的 MVC 项目中使用它的控制器添加一些继承。

所以我想做的是

public interface IListController<T> where T : ListModelBase<ListItemModelBase>
{
    T GetList(int Page, int ItemsPerPage);
}

那么我可以这样做:

public class OrderListController : IListController<OrderListModel>, BaseController
{
    public OrderListModel GetList(int Page, int ItemsPerPage)
    {

    }
}

但显然这是不可能的,因为 ListModelBase 需要应用泛型类型。

这里的目标是让我可以使用 IListController 接口来表示我可以假设 controller.GetList(1, 10) 将返回一个 ListModelBase,然后我可以随后假设返回的模型每个都有一个 Id列表部分中的项目。

这可能吗?还是有更好的方法来做我想做的事?

更新:

明确地说,我知道我可以在控制器级别定义多种类型,但这不是我想要的。

所以我知道我可以做到:

public interface IListController<T, TItemModel> 
      where T : ListModelBase<TListModel>
      where TItemModel : ListItemModelBase
{
    T GetList(int Page, int ItemsPerPage);
}

【问题讨论】:

  • 您发布的代码有什么问题?它对我来说编译得很好(当我添加一个扩展 ListItemModelBase 的虚拟 OrderListItemModel 时)。包括“我想做的是……”下的那一段。我不完全清楚你在问什么。
  • @dvnrrs 控制器实现中存在错误,它认为ListModel 正好是ListModelBase&lt;ListItemModelBase&gt;,而不是来自ListItemModelBase 的任何派生项。
  • @mhoff 很高兴看到一个例子,如果它实现了目标,不知道协方差是什么或如何使用它来获得我想要的。
  • 我明白了...是covariance/contravariance 你在追求什么(in/out 关键字)?这些被例如使用。 List&lt;T&gt; 以便 List&lt;T&gt; 可转换为 List&lt;V&gt; 如果 V : T
  • @dvnrrs List&lt;T&gt; 不是变体。无法使用Add 方法获取变体、强类型集合。

标签: c# generics inheritance interface


【解决方案1】:

松开 IListController 上的约束并执行类似的操作(如果您可以使用较小的类型,例如 IEnumerable,请不要在接口上公开 List&lt;T&gt;):

public abstract class ListItemModelBase
{
    public Guid Id { get; set; }
}

public class ListItem : ListItemModelBase
{
}

public abstract class ListModelBase<T> where T : ListItemModelBase
{
    public IEnumerable<T> Items { get; set; }
}

public class OrderListModel : ListModelBase<ListItem>
{
}

public interface IListController<T>
{
    T GetList(int page, int itemsPerPage);
}

public abstract class BaseController
{
}

public class OrderListController : BaseController, IListController<OrderListModel>
{
    public OrderListModel GetList(int page, int itemsPerPage)
    {
        return new OrderListModel();
    }
}

然后你可以这样做:

var controller = new OrderListController();
var orderListModel = controller.GetList(0, 10);
foreach (var kindOfA in orderListModel.Items)
{
    doSomeThing(kindOfA.Id);
}

【讨论】:

  • 所以没有办法将IListController 限制为仅属于 ListModelBase 的那些?
  • 当然,比如where T : ListModelBase&lt;ListItemModelBase&gt;?我认为这个问题的整个混乱来源是由于命名不当。如果您理顺您的类/接口名称并按照此答案中的大纲进行操作,您会没事的。抱歉我的任何困惑
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
相关资源
最近更新 更多