具有泛型类型的C#继承似乎正在创建不同的对象类型

时间:2017-05-09 14:34:26

标签: c# generics inheritance

我有一个用于实体框架的抽象类。然后我继承了类并在需要时覆盖。在这种情况下,我有一个我想要删除的帖子,我想删除与帖子相关的评论。逻辑很简单,但我似乎得到了奇怪的类型问题。

这是我所期望的。但是,entity.ID不存在。事实上,  实体对象根本没有属性(就visual studio intellisense而言)。我试图抛出它,它说它不能将Post转换为MyProject.Models.Post,即使它应该是完全相同的类。因此,似乎通过使用泛型类型并在继承期间将其强制转换,它正在创建一个同名的新类。

public abstract class MyAbstractService<T>
{
    public virtual void Delete<T>(T entity)
    {
        this.context.Set<T>().Remove(entity);
    }
}

public abstract class MyAbstractService :AbstractService<Post>
{
    public override void Delete<Post>(Post entity)
    {

        this.context.PostComments.RemoveRange(this.context.PostComments.Where(x => x.Post.ID == entity.ID));
        base.Delete(entity);
    }
}

我能够通过使用下面的方法解决这个类型的问题,但我不明白为什么这发生在第一位。我假设有一个更好的方法来处理这个比我在这里使用的铸造方法。如果没有其他选择,那么首先会发生什么?

public override void Delete<Post>(Post entity)
{
    MyProject.Models.Post pst = entity as MyProject.Models.Post;
    this.context.PostComments.RemoveRange(this.context.PostComments.Where(x => x.Post.ID == pst.ID));
    base.Delete(entity);
}

基于这些评论,似乎这样的东西将是实现删除的更优选方式,但是我仍然觉得抽象方法是有用的,因为我已经将它用于许多其他没有关系的实体。

public void Delete(Post entity)
{
    this.context.PostComments.RemoveRange(this.context.PostComments.Where(x => x.Post.ID == entity.ID));
    base.Delete(entity);
}

1 个答案:

答案 0 :(得分:2)

Delete上的MyAbstractService方法正在定义一种方法,表明任何MyAbstractService都可以删除任何类型的任何对象。

因此,当您从该抽象类继承并提供该方法的实现时,您需要提供一种能够删除任何类型的任何对象的方法。您已在实施中为您的通用类型Post命名(您可以随意调用它),但调用该通用参数Post并不代表实例属于Post类型,它只是通用类型的名称,因此对象可以是任何类型的 。如果您希望将对象视为Post类型的对象,则需要将其投射,就像您正在进行的那样。

现在你有了一个签名声明的方法它可以接受任何类型的对象,但实际上它只会失败,如果&# #39;不是Post类型的对象。这个糟糕的设计;你的API对其来电者说谎。

相反,对于MyAbstractService类型,有一个方法可以删除任何类型的对象,这是没有意义的。 Delete开始时不应该是通用的。相反,它应该只使用类的通用类型,而不是定义第二个泛型类型(你也称之为T,令人困惑)。