我发现了几个问题那个似乎与我的相似,但我无法从其中任何一个那里得到正常工作的答案。
我有一个非泛型抽象基类,一个从非泛型抽象基类继承的泛型基类,以及一些从泛型基类继承的类。到目前为止一切顺利。
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; }
我觉得我在这里错过了一些简单的东西,但我一直在盲目地努力。我看不到什么?
您的代码的问题是 IList 不是协变的(您可以在here阅读更多相关信息)
基本上发生的情况是,泛型继承并不像您想象的那样适用。例如 IList 既不继承自 IList
原因是因为 IList 有 Add 等方法,如果你可以将 IList 分配给 IList 就会出现问题,因为这样 Add 方法将接受 BaseTable,这意味着你可以将 MyFooTable 添加到最初是 MyBarTable 的 IList 中.
如果您阅读我上面分享的有关协方差/逆变的文章,所有这些都会更有意义。
现在,要解决您的代码问题,您需要选择一个适合您且在 T 上协变的接口。例如,IEnumerable、IReadOnlyCollection 或 IReadOnlyList。