C#泛型类继承编译时错误

时间:2015-06-03 15:19:52

标签: c# generics

我有以下代码:

public class EntitySchema
{
}

public class ContactEntitySchema : EntitySchema
{
}

public class ProductEntitySchema : EntitySchema
{
}

public class Entity<TEntitySchema>
    where TEntitySchema : EntitySchema
{
    public string Id { get; set; }
}

public class Contact : Entity<ContactEntitySchema>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Product : Entity<ProductEntitySchema>
{
    public string Name { get; set; }
}

public class ViewBase<TEntity>
    where TEntity : Entity<EntitySchema>
{
    public TEntity Entity { get; set; }
}

public class ContactView : ViewBase<Contact>
{
    public ContactView()
    {
    }
}

public class ProductView : ViewBase<Entity<EntitySchema>>
{
    public ProductView()
    {
    }
}

我为ContactView类收到以下错误:

  

错误1类型'Generics.Contact'不能用作泛型类型或方法'TEntity'中的类型参数'Generics.ViewBase<TEntity>'。没有从'Generics.Contact''Generics.Entity<Generics.EntitySchema>'的隐式引用转换。

然后我定义了ProductView有点不同,它成功编译。但是,在ProductView中,如果我想使用某些特定于产品的字段,我应该将Entity属性显式地转换为Product。有没有办法重新编写ContactView的声明,所以我可以指定实际的实体类型(在这种特殊情况下 - 联系)?

1 个答案:

答案 0 :(得分:1)

您遇到的问题是public class Entity<TEntitySchema>generically invariant。这意味着即使知道ContactEntitySchema : EntitySchema并不意味着编译器可以在ContactEntitySchema中替换EntitySchema ViewBase的泛型类型定义1}}。

(要明白为什么会这样,请考虑如果您尝试将List<Cat>视为List<Animal>会发生什么,反之亦然。)

我可能误解了您的问题,但首先您可以尝试直接在视图的类型参数中指定架构类型,使用类型约束来确保TEntity和{{1}之间的关系保留?: -

TSchema

或者,您可以将public class ViewBase<TEntity, TSchema> where TEntity : Entity<TSchema> where TSchema : EntitySchema { public TEntity Entity { get; set; } } public class ContactView : ViewBase<Contact, ContactEntitySchema> { public ContactView() { } } public class ProductView : ViewBase<Entity<EntitySchema>, EntitySchema> { public ProductView() { } } 更改为界面: -

Entity

允许您指定public interface IEntity<out TEntitySchema> where TEntitySchema : EntitySchema { string Id { get; set; } } public class Contact : IEntity<ContactEntitySchema> { public string Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } // etc 泛型类型参数是协变的(使用TEntitySchema关键字)。

任何一种解决方案都应该允许您在视图对象中以强类型方式访问out