我有以下规范来帮助说明问题:
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);
}
}
上述规范失败并显示以下消息:
Expected: System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.Dog] But was: 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
类型相当慢。
我是一名优秀的程序员,十分优秀!