带有泛型类型的C#继承似乎正在创建不同的对象类型
我有一个抽象类,用于实体框架。然后我继承该类并在需要时重写。在这种情况下,我有一篇文章要删除,我想删除与该文章相关的评论。逻辑很简单,但我似乎遇到了奇怪的类类型问题 这就是我所期望的效果。但是,带有泛型类型的C#继承似乎正在创建不同的对象类型,c#,generics,inheritance,C#,Generics,Inheritance,我有一个抽象类,用于实体框架。然后我继承该类并在需要时重写。在这种情况下,我有一篇文章要删除,我想删除与该文章相关的评论。逻辑很简单,但我似乎遇到了奇怪的类类型问题 这就是我所期望的效果。但是,entity.ID不存在。事实上 实体对象根本没有属性(就visual studio intellisense而言)。我试着将它转换为一个类,它说它不能将Post转换为MyProject.Models.Post,即使它应该是完全相同的类。因此,通过使用泛型类型并在继承过程中强制转换它,它似乎正在生成一个同
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);
}
}
您的
MyAbstractService
上的Delete
方法正在定义一个方法,该方法表示任何MyAbstractService
都可以删除任何类型的对象
因此,当您从该抽象类继承并提供该方法的实现时,您需要提供能够删除任何类型的任何对象的方法。您已经在实现中将泛型类型命名为Post
(您可以随意调用它),但是调用泛型参数Post
并不意味着实例的类型为Post
,这只是泛型类型的名称,因此对象可以是任何类型。如果要将对象视为类型为Post
的对象,则需要在执行时强制转换它
现在您有了一个方法,它的签名声明它可以接受任何类型的对象,但实际上,如果它不是Post
类型的对象,它就会失败。这是糟糕的设计;您的API对调用方撒谎
相反,
MyAbstractService
类型拥有一个可以删除任何类型对象的方法是没有意义的<代码>删除一开始不应该是通用的。相反,它应该只使用类的泛型类型,而不是定义第二个泛型类型(您也将其称为T
,这很容易混淆)。您在MyAbstractService
上的Delete
方法定义了一个表示任何MyAbstractService
都可以删除任何类型的对象的方法
因此,当您从该抽象类继承并提供该方法的实现时,您需要提供能够删除任何类型的任何对象的方法。您已经在实现中将泛型类型命名为Post
(您可以随意调用它),但是调用泛型参数Post
并不意味着实例的类型为Post
,这只是泛型类型的名称,因此对象可以是任何类型。如果要将对象视为类型为Post
的对象,则需要在执行时强制转换它
现在您有了一个方法,它的签名声明它可以接受任何类型的对象,但实际上,如果它不是Post
类型的对象,它就会失败。这是糟糕的设计;您的API对调用方撒谎
相反,
MyAbstractService
类型拥有一个可以删除任何类型对象的方法是没有意义的<代码>删除一开始不应该是通用的。相反,它应该只使用类的泛型类型,而不是定义第二个泛型类型(您也将其称为T
,这已经足够令人困惑了)。为什么要为Delete方法声明泛型类型参数T
?类泛型类型参数(也称为t
)指定的类型的方法的参数不是吗?(编辑:请参见下面的答案…)我似乎不喜欢在方法调用的类型括号中使用完整的命名空间。i、 e.Delete,它不允许我将它放在方法param前面,因为它使它成为与泛型指定的类型不同的类型as@DanHastings实际上,您不能命名您正在定义的泛型类型MyProject.Models.Post
。这不是您正在定义的新类型的有效标识符。它也不允许您将该类型作为方法的参数,因为您要覆盖的抽象类声明该方法参数是泛型类型,而不是MyProject.Models.Post
。为什么要为Delete方法声明泛型类型参数t
?类泛型类型参数(也称为t
)指定的类型的方法的参数不是吗?(编辑:请参见下面的答案…)我似乎不喜欢在方法调用的类型括号中使用完整的命名空间。i、 e.Delete,它不允许我将它放在方法param前面,因为它使它成为与泛型指定的类型不同的类型as@DanHastings实际上,您不能命名您正在定义的泛型类型MyProject.Models.Post
。这不是您正在定义的新类型的有效标识符。它也不允许您将该类型作为方法的参数,因为您要覆盖的抽象类声明该方法参数是泛型类型,而不是MyProject.Models.Post
。谢谢您的回答。第一部分有道理,但最后一段让我有点困惑。VS确实会发出警告,指出这两个参数的名称相同,但如果我试图更改它,就会出现错误。如果我完全删除泛型类型,我会在this.context.Set中得到一个错误,即T必须是引用类型。如果我更改它以便使用Delete(T entity),它表示它无法将T转换为Y。当两者都命名为T时,它可以工作。在所有情况下,这个方法都是有效的,我需要使它具有依赖性custom@DanHastings如果Set
表示需要使用引用类型的类型,请确保传递的类型是引用类型。创建不需要的其他类型只会给您带来问题。再说一次,你知道
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);
}