C# 为什么泛型类型不是正确的类型?
我有两个类,C# 为什么泛型类型不是正确的类型?,c#,generics,C#,Generics,我有两个类,BaseClass和Person。Person类继承自BaseClass。然后我使用以下通用方法 public static PropertyInfo GetProperty<T>(T item, Func<PropertyInfo, bool> predicate) { return GetProperty(typeof(T), predicate); } 然后,我从单元测试调用这个方法 var person = n
BaseClass
和Person
。Person
类继承自BaseClass
。然后我使用以下通用方法
public static PropertyInfo GetProperty<T>(T item, Func<PropertyInfo, bool> predicate)
{
return GetProperty(typeof(T), predicate);
}
然后,我从单元测试调用这个方法
var person = new Person();
person.DoSomething();
当使用typeof(T)
时,返回BaseClass
。如果我使用item.GetType()
,则返回Person。如果我在调试器中检查它们,T
类型为BaseClass
,item
类型为Person
。既然它已经知道项
是人,为什么不推断T
是类型的(人)
编辑
我上面的例子是错误的对不起,当我调用GetProperty时,我传递了这个
public class BaseClass
{
public void DoSomething()
{
var property = GetProperty(this, (property) => p.Name == "Name");
}
}
产生此推理问题的原因是泛型推理发生在编译时,因此与手动指定所需类型相同。如果在调用中切换到显式声明
,它是否会在编译期间抛出错误
解决这个问题的一种方法是确保传入的变量(注意:不是对象!)显式地属于Person
类,就像它在代码中一样。另一种方法是通过使用对象强制在运行时进行泛型推理:
GetProperty(this as dynamic, (prop) => prop.Name == "Name");
通过将this强制转换为动态
,它在运行时使用this
的确切类型调用GetProperty
。这种方法的问题是,与其他对象相比,动力学速度非常慢
如果您的模型严格来说是单级继承,那么还可以利用静态多态性来处理泛型参数。因此:
public class BaseClass<TSelf> where TSelf : BaseClass<TSelf>
public sealed class Model : BaseClass<Model>
公共类基类,其中TSelf:BaseClass
公共密封类模型:基类
这样,您可以使用TSelf
作为参数来代替T
,这将是完全正确的。这种方法的问题是,它严格地将您限制在单一继承层次结构中,因为从模型
继承的任何内容都会返回到原始问题,并被视为模型
,因为它无法覆盖其基类使用的泛型参数
假设您的GETFACKY函数做了一些检查来检查属性,您可能需要考虑传递<代码>类型对象,而不是使用泛型,然后使用<代码>类型(t)< /C> >,作为<代码> .GETType()
更准确。我的问题是,有30多个模型继承自我的基类,而我的视图模型称之为基类方法。向基类方法添加强类型泛型是多余的。您的第二个建议我不确定我是否理解,当从我的视图模型调用该方法时,我会提供这个建议吗<代码>this.SelectedModel.DoSomething()代码>?要回答您关于显式声明
的问题,它不会引发异常。在我的单元测试中,我有PersonFixture:BaseClass
,我调用PersonFixture.DoSomething()
。当我调试时,typeof(T)
是Person
我编辑了我的OP。我将this
传递给方法,并且this
调用发生在基类中。当我从基类中调用该方法时,是否应该传递this.GetType()
?要总结我更新的答案的最后一段,是的,您应该这样做,但我还包括了几个其他选项。感谢这些选项,这将解决我的问题。由于它位于缓存池中,我可能会保留基类的方法签名和调用,并更新typeof(T)以使用GetType()。我不想让用户记住在使用缓存时总是传递GetType():)如果编译器使用t
=BaseClass
关闭了泛型方法,那么程序仍将编译并运行,并且您将准确地看到所描述的输出。如果可行,您通常应该使用GetType()
,因为您将始终获得对象的具体类型。我不知道,但当我编译它时,它会正确地推断出Person
。将其作为完整代码发布。在BaseClass
的范围内,typeof(this)
始终是BaseClass
。但是,this.GetType()
重载并返回Person
。啊,好吧,我想typeof(this)
会知道this
是个孩子。谢谢你更新了问题,很清楚。在DoSomething
中,传递此
,它是基类
类型的对象。因此编译器正确地推断出类型为BaseClass
。
public class BaseClass<TSelf> where TSelf : BaseClass<TSelf>
public sealed class Model : BaseClass<Model>