在派生类调用的虚方法中输入此类型

时间:2012-05-02 12:50:42

标签: c# .net generics virtual-method

我发现自己处于这样一种情况:我在基类上有一个方法,它调用泛型方法将自身作为参数传递(通过this)。在泛型方法中,类型始终是基类型,即使我从派生类调用该方法。

我需要通用方法来知道它是派生类型而不是基类型。

我无法更改通用方法,因为它来自第三方应用程序(http://razorengine.codeplex.com/ - Razor.Parse方法)。

我发现如果我将方法定义为一个通用的扩展方法,限制为继承自我的基类的类型,那么调用它然后工作但是为此目的使用扩展方法似乎很麻烦(尽管如果这是正确的用法我'我很高兴听到这个消息。我想知道是否有一些我可以使用的技巧会在调用之前将“this”转换为派生对象的类型(可能仍使用泛型)。

我在下面添加了一个简化的程序,该程序应该是自包含的(我在LINQPad中运行它是为了方便)。基本上我想要在A上定义的方法,当在B的实例上调用时,将调用Test.WhatType并输出“B”。

我希望这是有道理的。

void Main()
{
    var bar = new B();
    bar.myGetType();
    bar.ExtGetType();
}

class A
{
    public virtual void myGetType()
    {
        Test.WhatType(this);
        this.ExtGetType();
    }
}

class B : A {}

static class ext
{
    public static void ExtGetType<T>(this T obj) where T : A
    {
        Test.WhatType(obj);
    }
}

class Test
{
    public static void WhatType<T>(T obj)
    {
        Console.WriteLine(typeof(T).Name);
    }
}

编辑:将方法名称更改为A.myGetType(),因为我甚至没有注意到我的意外超载。

N.B。运行此代码输出:

A
A
B

3 个答案:

答案 0 :(得分:3)

您需要使用obj.GetType()T在编译时绑定,而不是运行时绑定,因此typeof(T)返回编译时类型T

答案 1 :(得分:2)

如果我理解正确,您的问题是A.GetType()WhatType<A>绑定,因为它就是它所知道的。

所以你必须让类A知道派生类。

您可以使用自引用泛型类型来执行此操作。类似的东西:

class A<T> where T : A<T>
{
    public virtual void GetType()
    {
        Test.WhatType<T>( (T) this );
    }
}

class B : A<B> { }

然后:

new B().GetType();

将绑定到WhatType<B>,因此会输出B

答案 2 :(得分:-1)

此方法返回静态类型(T)的类型。它应该实现为

public static void WhatType<T>(T obj) 
{ 
    Console.WriteLine(obj.GetType().Name); 
} 

编辑: 我刚刚意识到你想要的是以通用方法的T改变的方式操纵A.您可以通过反射或通过添加基于A的子类型的switch语句来执行此操作,并将其显式转换为B(或任何类)。当然,没有一个解决方案是好的,因为A会依赖于它的子类和反射明显的sux。另一个选择是覆盖每个子类中的GetType()方法,从而将责任移到子类。