[英]Force calling the derived class implementation within a generic function in C#?
好的,所以我目前正在使用一些类,这些类在我使用这些对象的一些通用函数中无法控制。 我决定编写一个泛型函数,而不是编写实际上每个类都做相同事情的数十个函数。
现在,我正在处理的类有点怪异,因为派生类共享许多相同的属性,但派生自它们的基类却没有。 一个这样的属性示例是.Parent,它存在于大量派生类中,但不存在于基类中,我需要使用此属性。
为了便于理解,我创建了一个小示例,如下所示:
class StandardBaseClass {} // These are simulating the SMO objects
class StandardDerivedClass : StandardBaseClass {
public object Parent { get; set; }
}
static class Extensions
{
public static object GetParent(this StandardDerivedClass sdc) {
return sdc.Parent;
}
public static object GetParent(this StandardBaseClass sbc)
{
throw new NotImplementedException("StandardBaseClass does not contain a property Parent");
}
// This is the Generic function I'm trying to write and need the Parent property.
public static void DoSomething<T>(T foo) where T : StandardBaseClass
{
object Parent = ((T)foo).GetParent();
}
}
在上面的示例中,即使我强制将强制类型转换为T(即StandardDerivedClass),调用DoSomething()也会在GetParent()的基类实现中引发NotImplemented Exception。
这与其他转换行为相反,在其他转换行为中,通过向下转换将强制使用基类的实现。
我将此行为视为错误。 还有其他人遇到过这个吗?
我将此行为视为错误。
此行为是正确的。 由于您的方法DoSomething
将T
限制为StandardBaseClass
,因此您只能访问StandardBaseClass
的特定方法,而不能访问派生类的任何方法或属性。 由于StandardBaseClass
没有Parent
属性,因此在设计上这是无效的,并且应该无效。
这里有两个潜在的选择-您可以使用反射来拉出Parent属性,或者使用C#4的动态类型,并将其视为动态对象。 但是,两者都绕过了编译器中的标准类型检查,因此,您将需要在运行时进行额外的类型检查,以验证Parent属性是否存在。
创建一个包含Parent属性的接口。 让每个具有Parent属性的类都实现该接口。 然后,您将能够创建一个接受类型为IHaveParent
的参数的通用方法,它将做正确的事情。
对于对此情况有一个简洁答案的任何人,Stephen Cleary都会在msdn上回答:
对我来说,这是类层次结构上的分歧。 我的意思是,要么基类有父级,要么派生类具有Parent都派生自基层的抽象子级。
如约翰所说,哈哈,与抽象类相对的接口也足够。
您的想法将行不通,因为编译器永远无法保证基类实际上具有此类属性。 而且,它不会仅仅根据是否具有“正确”来选择它。
做到这一点的唯一方法是使用反射,然后在运行时进行测试,如果所检查的类上存在所请求的属性。 您必须判断自己是否对项目可行(反射缓慢且需要最大权限)。
这是正确的,因为编译器只知道它可以绑定到你的类型作为StandardBaseClass
。 绑定不会在运行时完成(绑定可能会决定使用StandardDerivedClass
重载。
如果您知道它是一个StandardDerivedClass
,那么为什么不就这样强制转换它呢?
object Parent = ((StandardDerivedClass)foo).Parent;
这有点丑陋,但是您可以使用注册系统来完成此任务,在该系统中,您可以为暴露“共享”属性/方法的各种可能的派生类注册委托,然后使用Dictionary<Type,Func<SomeT>>
进行存储代表们。 如果您提前知道所有派生类型,而不必加载插件等,则也可以使用经典的丑陋if / else-if结构。 无论哪种方式,您基本上都可以创建自己的替代方法,以替代虚拟方法表应支持的功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.