我试图理解为什么以下内容无法编译。编译器在CreatePresenter尝试设置View属性的行上抱怨:
无法将类型'Sandbox.Program.MyView'隐式转换为'TView'。
我知道作业的背景没有意义,更多的是为了说明。任何帮助都会很棒!
interface IView {
}
class Presenter<T> where T : IView {
public T View { get; set; }
}
class MyView : IView {
}
class MyPresenter : Presenter<MyView> {
public MyPresenter() { }
}
class ViewBase<TPresenter, TView>
where TPresenter : Presenter<TView>, new()
where TView : IView {
public TPresenter Presenter { get; private set; }
void CreatePresenter() {
this.Presenter = new TPresenter();
this.Presenter.View = new MyView();
}
}
答案 0 :(得分:7)
在线:
this.Presenter.View = new MyView();
您正在尝试将MyView
对象设置为泛型TView
的属性(实现IView
)。
这是错误的,因为MyView
与TView
不同,因此无法分配。{/ p>
修改强>
扩大一点......
你可以为其界面指定一个类型,例如:
IView v = new MyView(); // OK !
但你不能为其中一个实施者分配一个接口,例如:
IView v = ...;
MyView myView = v; // WRONG !
在这里,你正在做一些更复杂的事情,比如:
IView
_______|_______
| |
| |
TView <-- MyView
这显然是错误的。
实际上,即使TView
和MyView
实现了相同的接口,也允许此TView
继承MyView
但是在通用约束中没有指定,因此编译器不能做任何假设。
还要看davy8's answer一个明确的例子:)
答案 1 :(得分:1)
想象一下,你还有两个班级:
class MyView2 : IView
{
}
class MyPresenter2 : Presenter<MyView2>
{
public MyPresenter2() { }
}
然后尝试使用以下内容构建一个新的ViewBase:
var viewBase = new ViewBase<MyPresenter2, MyView2>();
在这种情况下,在您的方法中:
void CreatePresenter()
{
this.Presenter = new TPresenter();
this.Presenter.View = new MyView();
}
this.Presenter.View
MyView2
不会从MyView
继承,即使它们都实现了IView
答案 2 :(得分:0)
MyView
不保证属于同一类型TView
。您可以使用此通用类的IView
实现多个MyViews
。
如果您将ViewBase
更改为以下代码,则至少会编译。我不确定它会如何影响您的应用程序的行为。
class ViewBase<TPresenter, TView>
where TPresenter : Presenter<TView>, new()
where TView : IView, new()
{
public TPresenter Presenter { get; private set; }
void CreatePresenter()
{
this.Presenter = new TPresenter();
this.Presenter.View = new TView();
}
}