我发现自己处于这样一种情况:我在基类上有一个方法,它调用泛型方法将自身作为参数传递(通过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
答案 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()方法,从而将责任移到子类。