具有通用摘要列表的实体框架实体不能分配给非通用基础

问题描述 投票:0回答:1

我发现了几个问题那个似乎与我的相似,但我无法从其中任何一个那里得到正常工作的答案。

我有一个非泛型抽象基类,一个从非泛型抽象基类继承的泛型基类,以及一些从泛型基类继承的类。到目前为止一切顺利。

public abstract class BaseTable { }
public abstract class BaseTable<T> : BaseTable
{
    public int Id { get; set; }
    public T Value { get; set; }
}
public class Foo { }
public class Bar { }
public class MyFooTable : BaseTable<Foo> { }
public class MyBarTable : BaseTable<Bar> { }

当我使用这些类时,我无法将它们转换为非泛型基类:

public class SomethingThatUsesFoo
{
    public int Id { get; set; }
    public IList<MyFooTable> Table { get; set; }
}
public class SomethingThatUsesBar
{
    public int Id { get; set; }
    public IList<MyBarTable> Table { get; set; }

    public void DoIt()
    {
        Something.DoSomething(Table);
        Something.DoSomething<Bar>(Table);
    }
}

public static class Something
{
    public static void DoSomething(IList<BaseTable> table) { }
    public static void DoSomething<T>(IList<BaseTable<T>> table) { }
}

问题在于

DoSomething()
,这两种变体都不起作用。两者都会给出编译器错误,显示
IList<MyBarTable> is not assignable to parameter type IList<BaseTable>
IList<MyBarTable> to IList<BaseTable<Bar>>
)。

在此示例中,我可能可以通过使用

public IList<BaseTable> Table { get; set; }
来解决它,但在我的应用程序中,这些是具有导航属性的实体框架实体,并且必须引用它们正确的类型:

public DbSet<MyFooTable> MyFooTables { get; set; }
public DbSet<MyBarTable> MyBarTables { get; set; }
public DbSet<SomethingThatUsesFoo> FooUsage { get; set; }
public DbSet<SomethingThatUsesBar> BarUsage { get; set; }

我觉得我在这里错过了一些简单的东西,但我一直在盲目地努力。我看不到什么?

c# entity-framework generics abstract-class
1个回答
0
投票

您的代码的问题是 IList 不是协变的(您可以在here阅读更多相关信息)

基本上发生的情况是,泛型继承并不像您想象的那样适用。例如 IList 既不继承自 IList,也不继承自 IList。

原因是因为 IList 有 Add 等方法,如果你可以将 IList 分配给 IList 就会出现问题,因为这样 Add 方法将接受 BaseTable,这意味着你可以将 MyFooTable 添加到最初是 MyBarTable 的 IList 中.

如果您阅读我上面分享的有关协方差/逆变的文章,所有这些都会更有意义。

现在,要解决您的代码问题,您需要选择一个适合您且在 T 上协变的接口。例如,IEnumerable、IReadOnlyCollection 或 IReadOnlyList。

© www.soinside.com 2019 - 2024. All rights reserved.