我可以使用接口定义基本期望吗?

时间:2018-11-15 12:59:11

标签: c# interface

我有一组模型,它们与两个大型旧项目中的(几乎)匹配的数据结构配对。每个项目都位于API的任一侧,因此我想创建一个“ Globals”项目,这两个项目都可以继承,以确保某种形式的一致性,减少发生火灾的可能性,并开始对接口而非实现实施编程。

我的计划是使用接口创建一种可以继承但可以略有偏离的通用基础(由于一方面需要数据,而另一侧则不需要),但是我遇到了使用它们的问题以这种方式进行嵌套。

说我有两个界面:

namespace Example.Interfaces
{
    public interface A
    {
        int X { get; set; }
        int Y { get; set; }
    }

    public interface B
    {
        int J { get; set; }
        List<A> KLM { get; set; }
    }
}

如果我想在模型中使用这些功能,我将在下面做类似的事情。

namespace Example.Models
{
    public class Item : A
    {
        int X { get; set; }
        int Y { get; set; }
    }

    public class Container : B
    {
        int J { get; set; }
        List<Item> KLM { get; set; } // Wrong
    }
}

在这一点上,我的期望被证明是完全错误的(糟糕的derapasaurus,回到学校!)

在上面的示例中。在Container中,我希望能够定义List<>Item(如图所示),因为它们继承了A;显然不是这样,因为我看到警告告诉我应该将KLM定义为List<Interfaces.A>

如果我进行了Visual Studio建议的更改,则无法对字段Item进行类型KLM的分配,如下所示。

var derp = new Container
{
    J = 1
    KLM = new List<Item> { X = 123, Y = 456 }
};

然后我看到以下错误

  

无法将类型'Example.Models.Item'隐式转换为'Example.Interfaces.A'

我的问题是:

  • 这真的可以实现吗,还是由于将Item隐式转换为A而导致的潜在数据丢失,这是不可能的吗?
  • 是否有更好的方法在具有不同模型的两个项目之间实现基础(共享)字段的支架?
  • 我可以(我应该)做些修脚鞋吗?

1 个答案:

答案 0 :(得分:3)

要使其正常工作,您需要更改界面:

public interface B<T> where T:A
{
    int J { get; set; }
    List<T> KLM { get; set; }
}

在此情况下,接口的条件会强制实现该接口的类具有A类型的对象列表。

现在您的界面可以由您的课程实现:

public class Container : B<Item>
{
   public int J { get; set; }
   public List<Item> KLM { get; set; } 
}

如果您想在不知道具体类型的情况下对接口B进行读取访问,可以对此进行修改:

public interface B
{
    int J { get; set; }
    IEnumerable<A> KLM { get; }
}

public interface B<T> : B where T:A
{
    new List<T> KLM { get; set; }
}

实施:

public class Container : B<Item>
{
   public int J { get; set; }
   public List<Item> KLM { get; set; } 

   IEnumerable<A> B.KLM => KLM;
}