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>