返回实现变体接口的类

时间:2011-07-25 09:59:49

标签: c# generics casting covariance contravariance

背景

我有三个实现我的界面的Silverlight页面:

interface IPageWithData<in T> where T : Entity
{
    void SetData(T obj);
}

public class APage : Page, IPageWithData<AItem> { /* Implementation */ }
public class BPage : Page, IPageWithData<BItem> { /* Implementation */ }
public class CPage : Page, IPageWithData<CItem> { /* Implementation */ }

// AItem, BItem and CItem are (EF) Entities (they are derived from Entity class).

然后我使用一个自定义管理器,它返回一个与作为参数给出的树视图节点相关的页面:

private static class PageContainerHelper
{
    public static IPageWithData<Entity> SetPage(RadTreeViewItem selectedNode)
    {
        APageRTVI aNode = selectedNode as APageRTVI;
        BPageRTVI bNode = selectedNode as BPageRTVI;
        CPageRTVI cNode = selectedNode as CPageRTVI;

        if (aNode != null)
        {
            if (APage == null)
                APage = new APage();

            APage.SetData(aNode.aItem);
            return APage; // ERROR HERE
        }

        /*
            ... the same for BPageRTVI and CPageRTVI
        */
    }

    public static APage APage { get; set; }
    public static BPage BPage { get; set; }
    public static CPage CPage { get; set; }
}

问题:

我似乎以错误的方式理解共同/逆转。 SetPage()方法不允许我返回APage

  

无法将类型'MyProject.Views.Pages.APage'隐式转换为'MyProject.Views.Pages.IPageWithData'。存在显式转换(您是否错过了演员?)

APage实现IPageWithData<T>(虽然T是更多派生类型)。为什么这需要显式转换?显性转换甚至可以在这里工作吗?

基本上,我需要两件事。一个是当SetPage返回页面时,它可以使用实现IPageWithData类型的页面,该类型的派生类型比Entity更多。我需要的另一件事是IPageWithData<T>.SetData方法能够接收比T派生的类型更多的参数,即Entity

这可能吗?

1 个答案:

答案 0 :(得分:0)

考虑使用IPageWithData<Entity>可以做些什么。你可以这样做:

IPageWithData<Entity> pageWithData = PageContainerHelper.SetPage(...);
BItem item = new BItem();
pageWithData.SetData(item);

现在实施APage - 你希望它能用BItem做什么?我怀疑你不想那样。

换句话说,编译器正在做它应该做的事情 - 它保护您不会将错误类型的数据发送到无法处理它的页面。你真的想如何修复这个,我真的不知道 - 我怀疑你也希望SetPage是通用的:

public static IPageWithData<T> SetPage<T>(RadTreeViewItem selectedNode)
    where T : Entity

但我不清楚这对您的实施有何影响。