C# 从派生类调用的虚拟方法中的类型
我发现自己处于这样一种情况:我在基类上有一个方法,该方法调用一个将自身作为参数传递的泛型方法(通过C# 从派生类调用的虚拟方法中的类型,c#,.net,generics,virtual-functions,C#,.net,Generics,Virtual Functions,我发现自己处于这样一种情况:我在基类上有一个方法,该方法调用一个将自身作为参数传递的泛型方法(通过this)。在泛型方法中,类型始终是基类型,即使我从派生类调用该方法也是如此 我需要泛型方法知道它是派生类型而不是基类型 我无法更改通用方法,因为它来自第三方应用程序(http://razorengine.codeplex.com/ -Razor.Parsemethod) 我发现,如果我将该方法定义为一个泛型扩展方法,该方法仅限于从基类继承的类型,那么调用该方法是可行的,但为此目的使用扩展方法似乎很
this
)。在泛型方法中,类型始终是基类型,即使我从派生类调用该方法也是如此
我需要泛型方法知道它是派生类型而不是基类型
我无法更改通用方法,因为它来自第三方应用程序(http://razorengine.codeplex.com/ -Razor.Parse
method)
我发现,如果我将该方法定义为一个泛型扩展方法,该方法仅限于从基类继承的类型,那么调用该方法是可行的,但为此目的使用扩展方法似乎很麻烦(尽管如果这是正确的用法,我很高兴听到这一点)。我想知道的是,是否有一些技巧可以在调用之前将“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);
}
}
此方法返回静态类型(T)的类型。它应该作为一个整体来实施
public static void WhatType<T>(T obj)
{
Console.WriteLine(obj.GetType().Name);
}
公共静态void WhatType(T obj)
{
Console.WriteLine(obj.GetType().Name);
}
编辑:
我刚刚意识到,您想要的是以这样一种方式操纵A,即通用方法的T发生变化。您可以通过反射或基于a的子类型添加switch语句并显式地将其强制转换为B(或任何类)。当然,这些解决方案都不是好的,因为A将依赖于它的子类和反射。另一个选项是重写每个子类中的GetType()方法,从而将责任转移到子类。此方法返回静态类型(T)的类型。它应该作为一个整体来实施
public static void WhatType<T>(T obj)
{
Console.WriteLine(obj.GetType().Name);
}
公共静态void WhatType(T obj)
{
Console.WriteLine(obj.GetType().Name);
}
编辑:
我刚刚意识到,您想要的是以这样一种方式操纵A,即通用方法的T发生变化。您可以通过反射或基于a的子类型添加switch语句并显式地将其强制转换为B(或任何类)。当然,这些解决方案都不是好的,因为A将依赖于它的子类和反射。另一个选项是覆盖每个子类中的GetType()方法,从而将责任转移到子类。您需要使用
obj.GetType()
T
是在编译时绑定的,而不是在运行时绑定的,因此typeof(T)
返回编译时类型T
您需要使用obj.GetType()
T
是在编译时绑定的,而不是在运行时,因此typeof(T)
返回编译时类型T
如果我理解正确,您的问题是a.GetType()
绑定到WhatType
,这就是它所知道的一切
因此,您必须让classA
了解派生类
您可以使用自引用泛型类型执行此操作。比如:
class A<T> where T : A<T>
{
public virtual void GetType()
{
Test.WhatType<T>( (T) this );
}
}
class B : A<B> { }
将绑定到
WhatType
,因此将输出B
如果我理解正确,您的问题是A.GetType()
绑定到WhatType
,因为它只知道这些
因此,您必须让classA
了解派生类
您可以使用自引用泛型类型执行此操作。比如:
class A<T> where T : A<T>
{
public virtual void GetType()
{
Test.WhatType<T>( (T) this );
}
}
class B : A<B> { }
将绑定到
WhatType
,因此将输出B
,如果您的泛型方法关心类型,那么您需要重新评估该方法。嗯,这有点正确-调用的代码是A类!(我知道那没用)我会挖个洞,然后再打给你!您必须在WhatType方法中使用obj.GetType()。此外,GetType是对象上未标记为virtual的方法。请不要试图重写它。如果您的泛型方法关心类型,passwhere T:A
,那么您需要重新评估该方法。嗯,这有点正确-调用代码是类A!(我知道那没用)我会挖个洞,然后再打给你!您必须在WhatType方法中使用obj.GetType()。此外,GetType是对象上未标记为virtual的方法。请不要尝试重写它。typeof需要一个类型。我想你指的是obj.GetType(),它永远不会编译obj
不是typeof
的有效参数。它需要一个类型名称。一个注释,而不是对您的答案的批评:这只会起作用,因为您/OP没有将放置在t:a
中。如果添加该选项,则将使用A.GetType()
而不是Object.GetType()
。(A.GetType
的命名非常糟糕。)是的,事实上它会生成一个警告,因为A.GetType隐藏了Object.GetType(并且没有“new”关键字)。@hvd:我的命名非常糟糕A.GetType
已更改为A.myGetType
以区分它。谢谢你的观察。typeof需要一个类型。我想你指的是obj.GetType(),它永远不会编译obj
不是typeof
的有效参数。它需要一个类型名称。一个注释,而不是对您的答案的批评:这只会起作用,因为您/OP没有将放置在t:a
中。如果添加该选项,则将使用A.GetType()
而不是Object.GetType()
。(A.GetType
的命名非常糟糕。)是的,事实上它会生成一个警告,因为A.GetType隐藏了Object.GetType(并且没有“new”关键字)。@hvd:我的命名非常糟糕<密码