如何从具有基类型约束的泛型方法获取 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
类型。我可以在不使用反射的情况下做些什么吗?
这里的问题是运行时使用的类型与编译时使用的类型。
因为您将_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);
}
}