C#继承与泛型类似乎创建不同的对象类型

问题描述:

我有一个抽象类,我用于实体框架。然后,我会继承该类并在需要时重写。在这种情况下,我有一个帖子,我想删除,并与我想删除与帖子相关的评论。逻辑很简单,但我似乎越来越奇怪类类型的问题。C#继承与泛型类似乎创建不同的对象类型

这是我所期望的工作。但是,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); 
} 
+0

为什么你要为Delete方法声明一个泛型类型参数'T'?不是泛型类型参数(也称为'T')指定的类型方法的参数吗? (编辑:见下面的答案...) – elgonzo

+0

它似乎不喜欢当我在方法调用的类型括号中使用完整的命名空间。即删除,它不让我把它放在方法param的前面,因为它使它与泛型被指定为 –

+0

@DanHastings的不同类型。实际上,你不能命名你定义的MyProject的泛型类型。 Models.Post'。这不是您定义的新类型的有效标识符。它也不允许你将该类型作为你的方法的参数,因为你正在覆盖的抽象类声明方法参数是泛型类型,而不是'MyProject.Models.Post'。 – Servy

DeleteMyAbstractService方法是定义,指出任何MyAbstractService能够删除的任何类型任何对象的方法。

因此,当您从该抽象类继承并提供该方法的实现时,您需要提供一种能够删除任何类型的任何对象的方法。您已在实现中将您的通用类型Post命名(您可以随意调用它),但调用该通用参数Post并不意味着该实例的类型为Post,这只是泛型类型的名称,所以对象可以是任何类型的。如果你想对待对象,就好像它是Post类型的那样,你需要将它施放,就像你在做什么一样。

现在你有这就是签名索赔它可以接受的对象的任何类型的方法,但在现实中,如果不是Post类型的对象,它只会失败。这是糟糕的设计;你的API对其呼叫者撒谎。

相反,MyAbstractService类型有一种方法可以删除任何类型的对象。 Delete不应该是通用的开始。相反,它应该只使用类的泛型,而不是定义第二个泛型类型(您也称为T,足够容易混淆)。

+0

感谢您的答案。第一部分是有道理的,但最后一段我有点困惑。 VS确实给出了2个参数命名相同的警告,但是如果我试图改变它,我会得到错误。如果我完全删除泛型类型,我得到一个错误this.context.Set T必须是一个引用类型。如果我改变它,所以我使用删除(T实体)它说它不能将T转换为Y.当两者都被命名为T时,它可以工作。在所有情况下,这种方法已经工作,它刚刚与我需要使其自定义的依赖关系 –

+0

@DanHastings如果'Set'说你需要使用一个引用类型的类型然后*确保你传递的类型是一个引用类型*。创建你不想要的其他类型只会导致你的问题。同样,你不希望你的'Delete'方法能够接受任何类型的任何对象。你不打算提供这种行为,所以不要定义声称提供它的方法。 – Servy

+0

我已经用删除方法的更新示例更新了问题。我明白你的意思是我需要为特定的删除实现自定义功能。更新的方法起作用。但是,我使用抽象类中的删除方法来删除许多其他没有关系的实体,例如删除评论。如果我的抽象方法仍然错误,我应该怎么做才能纠正它?我希望它能够删除任何类型的实体,这就是它现在正在做的事情 –