为什么泛型类型不正确?

时间:2014-11-12 20:21:10

标签: c# generics

我有两个班级,BaseClassPersonPerson类继承自BaseClass。然后我使用以下通用方法。

    public static PropertyInfo GetProperty<T>(T item, Func<PropertyInfo, bool> predicate)
    {
        return GetProperty(typeof(T), predicate);
    }

BaseClass我有一个调用GetProperty

的方法
public class BaseClass
{
    public void DoSomething()
    {
        var property = GetProperty(new Person(), (property) => p.Name == "Name");
    }
}

然后我从单元测试中调用此方法。

var person = new Person();
person.DoSomething();

使用typeof(T)时,会返回BaseClass。如果我使用item.GetType()则返回Person。如果我在调试器中检查它们,T类型为BaseClassitem类型为Person。当T已经知道typeof(Person)是个人时,为什么不推断itemthis

修改

我的例子上面的错误很抱歉,当我致电GetProperty时,我通过了public class BaseClass { public void DoSomething() { var property = GetProperty(this, (property) => p.Name == "Name"); } }

{{1}}

1 个答案:

答案 0 :(得分:2)

这个推理问题的原因是通用推理在编译时发生,因此与手动指定所需类型相同。如果切换到使用调用显式声明<Person>,它是否在编译期间抛出错误?

解决这个问题的一种方法是确保传入的变量(注意:不是对象!)明确属于Person类,因为它似乎在您的代码中。另一种方法是通过使用dyanmic对象强制在运行时进行泛型推理:

GetProperty(this as dynamic, (prop) => prop.Name == "Name");

通过投射this as dynamic,它会在运行时使用GetProperty<dynamic>的确切类型调用this。这种方法的问题在于动态与其他对象相比非常慢。

如果模型严格来说是单个继承级别,您还可以使用静态多态来处理泛型参数。正是如此:

public class BaseClass<TSelf> where TSelf : BaseClass<TSelf>

public sealed class Model : BaseClass<Model>

通过这种方式,您可以使用TSelf作为参数代替T,这样就完全正确了。这种方法的问题在于它严格限制您使用扁平的单继承层次结构,因为从Model继承的任何内容都会返回到原始问题并被视为Model,因为它可以&#39; t覆盖其基类使用的泛型参数。

假设您的GetProperty函数执行了一些反射以检查属性,您可能需要考虑将Type对象传入,而不是使用泛型,然后typeof(T).GetType()更加准确。