如何从具有基类型约束的泛型方法获取typeof(T)? [英] How to get the typeof(T) from a generic method with base type constraint?
问题描述
我有以下规范来帮助说明问题:
class when_getting_type_of_generic_argument_using_subtype_instance
{
static GenericTypeTester _genericTypeTester;
静态IPet _dog;
static Type _result;
建立上下文=
()=>
{
_genericTypeTester = new GenericTypeTester();
_dog = new Dog();
};
因为=
()=> _result = _genericTypeTester.Test(_dog);
它should_return_the_subtype =
()=> _result.ShouldEqual(_dog.GetType());
}
class Dog:IPet
{
}
接口IPet
{
}
class GenericTypeTester
{
public Type Test< T>(T dog)其中T:IPet
{
return typeof(T);
$ b $ p
$ b 上面的规格失败并显示以下消息: p>
预期:System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.Dog]
但是:System.RuntimeType:[Pepino .ScenarioRunner.Selenium.Specs.IPet]
我需要结果为 Dog
。有没有什么我可以做,而不使用反射?
解决方案这里的问题是在运行时与编译时使用的类型。 / p>
因为您将 _dog
声明为 IPet
,变量在编译时传递给泛型方法的是 IPet
,尽管在运行时是 Dog
。因此,即使运行时的对象是 Dog
,编译器也会为泛型参数使用 IPet
。由于您使用了 typeof(T)
,因此您可以获得编译器提供给泛型方法的确切类型。
这可以通过将 _dog
的类型更改为 Dog
而不是 IPet
,这会使编译器推断出正确的类型。
这也可以通过将对象明确地转换为动态来避免
:
()=> _result = _genericTypeTester.Test(_dog as dynamic);
这将强制编译器阻止类型推断直到运行时,此时它会确定该对象是类型 Dog
。这通常不是生产代码的好主意,但是,因为动态
类型相当慢。
I have the following spec to help illustrate the problem:
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);
}
}
The spec above fails with the following message:
Expected: System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.Dog]
But was: System.RuntimeType:[Pepino.ScenarioRunner.Selenium.Specs.IPet]
I need the result to be of type Dog
. Is there something I can do without using reflection?
解决方案 The issue here is the type being used at runtime versus compile time.
Because you declared _dog
as an IPet
, the variable passed into the generic method is an IPet
at compile time despite being a Dog
at runtime. Thus the compiler uses IPet
for the generic parameter, even though the object at runtime is a Dog
. Since you used typeof(T)
, you get the exact type given to the generic method by the compiler.
This can be seen by changing the type of _dog
to Dog
instead of IPet
, which will then cause the compiler to infer the correct type.
This can also be avoided by explicitly casting the object as dynamic
:
() => _result = _genericTypeTester.Test(_dog as dynamic);
Which will force the compiler to hold off the type inference until runtime, at which point it will determine that the object is type Dog
. This is generally not a good idea for production code, however, since dynamic
types are rather slow.
这篇关于如何从具有基类型约束的泛型方法获取typeof(T)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!