如何从具有基本类型约束的泛型方法中获取 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;
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
类型相当慢。
只需将约束 "class" 添加到您的方法中即可:
class GenericTypeTester
{
public Type Test<T>(T dog) where T : IPet, class
{
return typeof (T);
}
}
我有以下规范来帮助说明问题:
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
类型相当慢。
只需将约束 "class" 添加到您的方法中即可:
class GenericTypeTester
{
public Type Test<T>(T dog) where T : IPet, class
{
return typeof (T);
}
}