【问题标题】:Can not figure out why this will not compile无法弄清楚为什么这不会编译
【发布时间】:2011-03-02 05:14:53
【问题描述】:

我试图了解为什么以下内容无法编译。编译器在 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();
        }
    }

【问题讨论】:

  • 您使用的是什么版本的 .NET?
  • 演示者的视图必须始终是具体MyView的实例吗?
  • @Michael - 他发布了它。无法转换类型。
  • @BoltClock 就像我说的,这仅用于说明目的。任务真的是“这个”

标签: c# .net .net-4.0


【解决方案1】:

上线:

this.Presenter.View = new MyView();

您正在尝试将MyView 对象设置为泛型类型TView 的属性(实现IView)。

这是错误的,因为MyViewTView 不同,因此无法分配。

编辑:

稍微扩展一下……

可以为其接口分配一个类型,例如:

IView v = new MyView(); // OK !

但您不能将接口分配给其实现者之一,例如:

IView v = ...;
MyView myView = v; // WRONG !

这里你正在做一些更复杂的事情,像这样:

        IView
   _______|_______
  |               |
  |               |
TView    <--   MyView

这显然是错误的。
事实上,即使TViewMyView 实现了相同的接口,要允许这个TView 应该从MyView 继承,但是在通用约束中没有指定,所以编译器不能做任何假设。

也可以查看davy8's answer 以获得明确的示例:)

【讨论】:

  • 我正要提交答案时,出现了类似 V 的描述 ;) +1。
  • 即使 MyView 实现了 IView ?
  • @Marco 这无关紧要,因为例如 int 和 BigInt 都实现了 IComparable,您不能将 BigInt 设置为 int。
  • @Yuriy 好的,这是有道理的。我只是在学习 co/contra 方差,我认为这将允许这种类型的代码。
  • @Marco 查看我的答案,了解为什么它不能工作的具体例子。
【解决方案2】:

假设您还有 2 个类:

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.ViewMyView2,它不继承自 MyView,即使它们都实现了 IView

【讨论】:

    【解决方案3】:

    MyView 不保证与TView 的类型相同。使用这个泛型类,您可以拥有多个不是 MyViewsIView 实现。

    如果您将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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 2023-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多