这些类可以实现这些接口吗?

时间:2018-07-20 19:55:54

标签: c# generics interface covariance

我正在尝试创建以下类。

但是我在努力获取几个View Model类来实现接口,如下所述。

数据模型类:

public interface IPage
{
    string PageTitle { get; set; }
    string PageContent { get; set; }
}
public interface IDatedPage
    : IPage
{
    DateTime PageDate { get; set; }
}



public abstract class Page
    : IPage
{
    public string PageTitle { get; set; }
    public string PageContent { get; set; }
}
public abstract class DatedPage
    : Page
    , IDatedPage
{
    public DateTime PageDate { get; set; }
}



public class AboutPage
    : Page
    , IPage
{
}
public class NewsPage 
    : DatedPage
    , IDatedPage
{
}

相关的视图模型类:

public interface IPageAdminViewModel<T>
    where T : IPage
{
    IPagedList<T> Pages { get; set; }
}
public interface IDatedPageAdminViewModel<T>
    : IPageAdminViewModel<T>
    where T : IDatedPage
{
}


public abstract class PageAdminViewModel<T>
    : IPageAdminViewModel<T>
    where T: IPage
{
    public IPagedList<T> Pages { get; set; }
}
public abstract class DatedPageAdminViewModel<T>
    : PageAdminViewModel<T>
    , IDatedPageAdminViewModel<T>
    where T : IDatedPage
{
}


public class AboutPageAdminViewModel
    : PageAdminViewModel<AboutPage>
    , IPageAdminViewModel<IPage>
{
}

public class NewsPageAdminViewModel
    : DatedPageAdminViewModel<NewsPage>
    , IDatedPageAdminViewModel<IDatedPage>
{
}

问题

我无法获得AboutPageAdminViewModel来实现IPageAdminViewModel<IPage>

类似地,NewsPageAdminViewModel将不会实现IDatedPageAdminViewModel<IDatedPage>

  

“ AboutPageAdminViewModel”未实现接口成员“ IPageAdminViewModel .Pages”。 'PageAdminViewModel .Pages'无法实现'IPageAdminViewModel .Pages',因为它没有匹配的返回类型'IPagedList '。


我尝试过的1:

我尝试将out添加到接口定义的通用参数中,如下所示:

public interface IPageAdminViewModel<out T>
    where T : IPage
{
    IPagedList<T> Pages { get; set; }
}
public interface IDatedPageAdminViewModel<out T>
    : IPageAdminViewModel<T>
    where T : IDatedPage
{
}

但是它给了我错误:

  

无效方差:类型参数“ T”必须在“ IPageAdminViewModel.Pages”上始终有效。 “ T”是协变的。

它不允许我将out添加到.Pages属性:

  

无效的方差修饰符。只能将接口和委托类型参数指定为变量。


我尝试过的2:

我已经了解到the out parameter doesn't play nicely with List<>,所以我尝试将所有IPagedList属性更改为IEnumerable。但是我仍然得到;

  

“ AboutPageAdminViewModel”未实现接口成员“ IPageAdminViewModel .Pages”。 'PageAdminViewModel .Pages'无法实现'IPageAdminViewModel .Pages',因为它没有匹配的返回类型'IEnumerable '。


更新

我正在尝试将其分解为较小的问题,这是第一个问题:

Generic parameter - using a concrete type compiles, but an implemented interface does not

1 个答案:

答案 0 :(得分:0)

public class AboutPageAdminViewModel
    : PageAdminViewModel<AboutPage>
    , IPageAdminViewModel<IPage>
{
}

您在课堂上遇到的两个约束彼此矛盾。 PageAdminViewModel<AboutPage>表示Pages集合返回一组AboutPage,并且仅接受AboutPage。而IPageAdminViewModel<IPage>Pages返回任何IPage,也可以接受任何IPage。因此,尽管一个约束只保证AboutPage,另一个约束为任何IPage打开了大门。简而言之,不允许,如果允许的话,您可以从ProfilePage集合中获得Pages,仅仅是因为它也是IPage。获得两种行为的唯一方法是分别实现每个Pages集合。