【问题标题】:Check constraint on generic interface检查泛型接口的约束
【发布时间】:2018-04-21 10:16:57
【问题描述】:

我有一个界面如下:

public interface IHasDetailPage<TViewModel> where TViewModel : ViewModelBase 
{
    TViewModel GetViewModel();
}

稍后在我的代码中,我有一个我知道实现此接口的对象。但是,在编译时,我确实知道它使用的特定类型参数。我想通过调用上述函数来检索该对象的 ViewModel:

ModelBase Target = DbHelper.Find(... // Retrieves this object from the database
if(Target is IHasDetailPage<ViewModelBase>)
{
    ViewModel = (Target as IHasDetailPage<ViewModelBase>).GetViewModel();
}

同样,我知道Target 实现了IHasDetailPage,并且 ViewModel 是ViewModelBase 的子类。但是这个 if 语句失败了,如果我删除它,强制转换失败(返回 null)。我假设是因为 Target 没有专门实现 IHasDetailPage&lt;ViewModelBase&gt;,而是 IHasDetailPage&lt;SpecificViewModel&gt;,甚至是强硬的 SpecificViewModel : ViewModelBase

如何执行此类型检查并正确转换?真的,我所需要的只是能够调用GetViewModel(),但我想了解如何正确完成此操作,以及为什么我的方法不起作用。

【问题讨论】:

  • 这里的ModelBase 是什么?
  • 它是每个模型都继承自的基类。在编译时我不知道具体的类型。此继承树与 ViewModelBase 继承树无关。

标签: c# generics interface subclass superclass


【解决方案1】:

如果您可以控制界面,则可以使其成为协变的。以下测试通过...

    [TestMethod]
    public void DetailPage_ShouldBeOfFooType()
    {
        var target = new Target();
        Assert.IsTrue(target is IHasDetailPage<Foo>);
    }

    public class Foo { }
    public class Bar : Foo { }
    public interface IHasDetailPage<out TViewModel> where TViewModel : Foo
    {
        TViewModel GetViewModel();
    }
    public class Target : IHasDetailPage<Bar>
    {
        public Bar GetViewModel() { return null; }
    }

【讨论】:

  • 谢谢!我在接口类型声明中添加了out,它现在可以工作了。我不知道协方差,但我现在查了一下,它似乎很有用;我希望我很久以前就知道它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
相关资源
最近更新 更多