返回实现变体接口的类
背景:
我有三个 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
是更派生的类型)。为什么这需要显式转换?显式转换在这里还能工作吗?
基本上,我需要两件事。一是当 SetPage
返回页面时,它可以使用实现比 Entity
更派生的类型的 IPageWithData
的页面。我需要的另一件事是 IPageWithData
方法能够接收比 T
更派生的类型的参数,即 <代码>实体。
这可能吗?
Background:
I have three Silverlight Pages, that implement my interface:
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).
Then I use a custom manager that returns a page that relates to the treeview node given as a parameter:
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; }
}
Problem:
I seem to be understanding co/contravariance the wrong way.
The SetPage()
method doesn't allow me to return APage
:
Cannot implicitly convert type 'MyProject.Views.Pages.APage' to 'MyProject.Views.Pages.IPageWithData'. An explicit conversion exists (are you missing a cast?)
APage
implements IPageWithData<T>
(albeit T
is of a more derived type). Why does this require a explicit conversion? And would an explicit conversion even work here?
So basically, there are two things I need. One is that when SetPage
is returning a page, it can use a page that implements IPageWithData
of a type that is more derived than Entity
. And the other thing I need is for the IPageWithData<T>.SetData
method to be able to receive arguments that are of a type more derived than a T
, that is Entity
.
Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
考虑一下您可以使用
IPageWithData
做什么。您可以这样做:现在实现是一个
APage
- 您希望它能够使用BItem
做什么?我怀疑你不希望这样。换句话说,编译器正在做它应该做的事情 - 它保护您免于将错误类型的数据发送到无法处理它的页面。你想如何修复这个问题,我真的不知道 - 我怀疑你也希望
SetPage
是通用的:但我不清楚这对你有什么影响执行。
Consider what you can do with
IPageWithData<Entity>
. You can do:Now the implementation is an
APage
- what would you want it to be able to do with aBItem
? I suspect you don't want that.In other words, the compiler is doing exactly what it should - it's protecting you from sending the wrong kind of data to a page which can't handle it. Quite how you want to fix this, I don't really know - I suspect you want
SetPage
to be generic too:but it's not clear to me what that does to your implementation.