如何从具有基类型约束的泛型方法获取typeof(T)? [英] How to get the typeof(T) from a generic method with base type constraint?

查看:244
本文介绍了如何从具有基类型约束的泛型方法获取typeof(T)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆