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

时间:2015-01-05 16:28:52

标签: c# .net generics

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

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类型。有没有我可以做的事情而不使用反射?

2 个答案:

答案 0 :(得分:2)

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

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

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

通过将对象明确地转换为dynamic

,也可以避免这种情况
() => _result = _genericTypeTester.Test(_dog as dynamic);

这会强制编译器在运行时延迟类型推断,此时它将确定对象是类型Dog。但是,这通常不是生产代码的好主意,因为dynamic类型相当慢。

答案 1 :(得分:0)

只需将约束“class”添加到您的方法中:

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