如何从具有基类型约束的泛型方法获取 typeof(T)

本文关键字:获取 泛型方法 typeof 约束 类型 基类 | 更新日期: 2023-09-27 18:36:12

我有以下规范来帮助说明问题:

class when_getting_type_of_generic_argument_using_subtype_instance
{
    static GenericTypeTester _genericTypeTester;
    static IPet _dog;
    static Type _result;
    Establish context =
        () =>
        {
            _genericTypeTester = new GenericTypeTester();
            _dog = new Dog();
        };
    Because of =
        () => _result = _genericTypeTester.Test(_dog);
    It should_return_the_subtype =
        () => _result.ShouldEqual(_dog.GetType());
}
class Dog : IPet
{
}
interface IPet
{
}
class GenericTypeTester
{
    public Type Test<T>(T dog) where T : IPet
    {
        return typeof (T);
    }
}

上述规范失败,并显示以下消息:

预期: System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.Dog] 但是是:System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.IPet]

我需要结果是 Dog 类型。我可以在不使用反射的情况下做些什么吗?

如何从具有基类型约束的泛型方法获取 typeof(T)

这里的问题是运行时使用的类型与编译时使用的类型。

因为您将_dog声明为IPet,所以传递到泛型方法的变量在编译时是一个IPet,尽管在运行时是一个Dog。因此,编译器使用 IPet 作为泛型参数,即使运行时的对象是 Dog 。由于您使用了 typeof(T) ,因此您可以获得编译器为泛型方法提供的确切类型。

这可以通过将_dog的类型更改为Dog而不是IPet来看到,这将导致编译器推断出正确的类型。

也可以通过将对象显式转换为dynamic来避免这种情况:

() => _result = _genericTypeTester.Test(_dog as dynamic);

这将迫使编译器将类型推断推迟到运行时,此时它将确定对象是类型 Dog 。但是,对于生产代码来说,这通常不是一个好主意,因为dynamic类型相当慢。

只需将 constrait "class" 添加到您的方法中:

 class GenericTypeTester
 {
   public Type Test<T>(T dog) where T : IPet, class
   {
     return typeof (T);
   }
 }