不兼容的泛型类型

本文关键字:泛型类型 不兼容 | 更新日期: 2023-09-27 18:30:49

我不明白为什么我不能在另一个泛型的定义中使用特定的泛型类型。

所以我有这个:

public abstract class MdiWorkspaceController<TWorkItemController, TMdiWorkspaceView, TWorkItemViewFrame, TWorkItemMainView> 
    : ViewableWorkspaceController<TWorkItemController>
    where TMdiWorkspaceView : class, IMdiWorkspaceView<TWorkItemViewFrame, TWorkItemMainView, TWorkItemMainView>
    where TWorkItemViewFrame : class, IWorkItemViewFrame<TWorkItemMainView>
    where TWorkItemMainView : class, IWorkItemMainView
    where TWorkItemController : ViewableWorkItemController{}

和我试图使用

  public partial class TabbedWorkspaceView<TWorkItemMainView>
        : KryptonNavigator,
        IMdiWorkspaceView<TabbedWorkItemViewFrame<TWorkItemMainView>, TWorkItemMainView, TWorkItemMainView>
        where TWorkItemMainView : AbstractWorkItemView

作为更具体的实现中的TTabbedWorkspaceView选项卡式工作区控制器,如下所示:

public class TabbedWorkspaceController<TWorkItemController, TTabbedWorkspaceView, TTabbedWorkItemViewFrame, TWorkItemMainView>
    : MdiWorkspaceController<TWorkItemController, TTabbedWorkspaceView, TTabbedWorkItemViewFrame, TWorkItemMainView>
    where TWorkItemController : ViewableWorkItemController
    where TTabbedWorkspaceView : TabbedWorkspaceView<TWorkItemMainView>
    where TTabbedWorkItemViewFrame : TabbedWorkItemViewFrame<TWorkItemMainView>
    where TWorkItemMainView : AbstractWorkItemView

但是我收到一个错误,说TTabbedWorkspaceView必须可转换为

IMdiWorkspaceView<TTabbedWorkItemViewFrame<TWorkItemMainView>, TWorkItemMainView, TWorkItemMainView>

为了将其用作泛型类中的参数 TMdiWorkspaceView

 MdiWorkspaceController<TWorkItemController, TTabbedWorkspaceView, TTabbedWorkItemViewFrame, TWorkItemMainView>

现在我会很高兴地承认我处于"聪明"代码的个人边界,但在此之后,一切都在应用程序级别变得完全具体和简化,所以我想继续使用我拥有的设计。

更新:

好的,感谢大家的帮助,我已经解决了这个问题,我需要让泛型类型流向 TabbedWorkspaceView,而不是我已经声明了它。所以新版本是:

 public partial class TabbedWorkspaceView<TTabbedWorkItemViewFrame, TWorkItemMainView>
        : KryptonNavigator,
        IMdiWorkspaceView<TTabbedWorkItemViewFrame, TWorkItemMainView, TWorkItemMainView>
        where TTabbedWorkItemViewFrame : TabbedWorkItemViewFrame<TWorkItemMainView>
        where TWorkItemMainView : AbstractWorkItemView

然后:

 public class TabbedWorkspaceController<TWorkItemController, TTabbedWorkspaceView, TTabbedWorkItemViewFrame, TWorkItemMainView>
        : MdiWorkspaceController<TWorkItemController, TTabbedWorkspaceView, TTabbedWorkItemViewFrame, TWorkItemMainView>
        where TWorkItemController : ViewableWorkItemController
        where TTabbedWorkspaceView : TabbedWorkspaceView<TTabbedWorkItemViewFrame, TWorkItemMainView>
        where TTabbedWorkItemViewFrame : TabbedWorkItemViewFrame<TWorkItemMainView>
        where TWorkItemMainView : AbstractWorkItemView

然后在应用程序级别,我可以:

public class TappWorkspaceController
    : TabbedWorkspaceController<TappWorkItemController, TappWorkspaceView, TappWorkItemViewFrame, TappWorkItemView>

不兼容的泛型类型

我认为这篇文章是相关的:

约束不是签名的一部分

你的问题伤害了我的大脑,但我相信这就是正在发生的事情:

  • 编译器并不"知道"TTabbedWorkspaceView是一个TabbedWorkspaceView,因为这个信息只是通过一个不是签名一部分的约束给出的。

  • TTabbedWorkspaceView通过TabbedWorkspaceController的继承作为TMdiWorkspaceView传递给MdiWorkspaceController

  • MdiWorkspaceController的约束验证在TMdiWorkspaceView失败,因为它被赋予为不"已知"为IMdiWorkspaceView的东西。

解决方案:CA1005。

可以在另一个泛型类型的定义中使用泛型类型。这是一个简化的示例:

class Program
{  
    public interface IBadFoo
    {
        void DoSomethingUnusual();
    }
    public interface IFoo
    { 
        void DoSomething();
    }
    public class Foo : IFoo
    {
        public void DoSomething()
        {           
        }
    }
    public abstract class SomeGenericBase<IFooClass>
        where IFooClass : IFoo
        //where IFooClass : IBadFoo
    {
        public abstract void DoSomethingElse();
    }
    public class SomeGeneric<FooClass> : SomeGenericBase<FooClass>
        where FooClass : Foo, new()
    {
        public override void DoSomethingElse()
       {
           FooClass fc = new FooClass();
           fc.DoSomething();
       }
   }
   public static void Main()
   {
       SomeGeneric<Foo> someGen = new SomeGeneric<Foo>();
       someGen.DoSomethingElse();
   }
}

请注意,如果我where IFooClass : IFoo评论并取消注释//where IFooClass : IBadFoo那么我会收到类似的错误,因为没有从Foo到IBadFoo的转换。因此,我认为在您的继承结构和参数中的某个地方,编译器没有路径或路径不匹配。我建议您删除参数并简化问题空间,直到找到源。

这段代码真的很复杂,我花了一段时间才解开它(我仍然不明白它应该是什么意思)。

我认为问题在于MdiWorkspaceController要求其TMdiWorkspaceViewTWorkItemViewFrame直接相关,但你不能保证这一点。

要解决此问题,您可以将IMdiWorkspaceView界面更改为:

public interface IMdiWorkspaceView<TWorkItemViewFrame, T2, T3>

自:

public interface IMdiWorkspaceView<in TWorkItemViewFrame, T2, T3>

in基本上放宽了对TWorkItemViewFrame的要求,这将使你的代码编译。

如果IMdiWorkspaceView的定义是这样的,它不会用in编译,这意味着你编写的代码不是类型安全的。