如何检测是否在c#中重写了虚方法
是否可以确定是否已覆盖虚拟方法:
class ABase { public void DoSomething(object p) { p.Process(); if( /* DoSomethingExtra is implemented */ ) DoSomethingExtra(p); } public virtual void DoSomethingExtra(object p) { } } class ADerived { public override void DoSomethingExtra(object p) { p.ProcessMore(); } }
我意识到这个例子看起来很愚蠢(例如,你为什么不调用DoSomethingExtra(),因为它没有做任何事情)。 我向你保证,我有一个合法的案例。 有任何想法吗?
检查一下使用Reflection(C#)检测方法是否被覆盖
reflection将是在运行时执行此操作的唯一方法。 这应该带有健康警告,但是,从OOP的角度来看,它应该被认为是一个非常糟糕的想法(tm)。 基类通常不应该知道或关心如何实现派生类。
所以在C#中可以声明一个虚方法而不实现它。
这是不可能的。 您可以将方法声明为抽象 ,但如果该方法是虚拟的,则它将具有一些实现(即使实现实际上是空操作)。
上面的代码报告错误Error 1 'ABase.DoSomethingExtra(object)' must declare a body because it is not marked abstract, extern, or partial
。
处理此问题的典型方法是使用null op实现声明方法,并调用它:
class ABase { public void DoSomething(object p) { p.Process(); DoSomethingExtra(p); // Always call } public virtual void DoSomethingExtra(object p) { // Do nothing here } }
编辑:既然您的问题已被编辑,我将为您提供与您的编辑相关的更多信息,特别是:
我意识到这个例子看起来很愚蠢(例如,你为什么不调用DoSomethingExtra(),因为它没有做任何事情)。 我向你保证,我有一个合法的案例。 有任何想法吗?
没有直接的方法来确定当前实例是否覆盖了您的虚方法。 这可能需要一些非常讨厌,不可维护的代码,例如通过reflection检查方法体声明类型 ,看看有什么。
话虽如此,我强烈质疑这里的设计目标。 你的问题基本上是要求一种违反Liskov替换原则的特定方式,这是面向对象编程的核心原则之一。 这将导致您的代码性能降低,维护性降低……
反思是这个问题的一个很好的答案。
using System.Reflection; Type classType = typeof(ADerived); MethodInfo method = classType.GetMethod("DoSomethingExtra"); if (method.DeclaringType == typeof(ABase)) Console.WriteLine("DoSomethingExtra not overridden."); else Console.WriteLine("DoSomethingExtra is overridden by " + method.DeclaringType.Name);
我希望你会发现这很有用。
一旦我实现了一个特殊的对象查看器,当对象未知时,我将使用ToString(),除非它没有被覆盖。
有几个选择:
如果派生类必须实现DoSomethingExtra()
,则将方法和类声明为abstract
。 这将迫使具体派生类具有实现。 然后,您可以从基类代码调用DoSomethingExtra()
,知道将存在实现。
abstract class ABase { public void DoSomething(object p) { p.Process(); DoSomethingExtra(p); } public abstract void DoSomethingExtra(object p); }
如果派生类可以实现该方法,那么只需在基类中包含一个默认实现,如果没有派生实现可用,则将调用该实现。
另一种选择是有一个派生类可以设置的标志,指示他们是否需要额外的东西来完成:
class ABase { public virtual bool ShouldDoSomethingExtra { get { return false; } } public void DoSomething(object p) { p.Process(); if(ShouldDoSomethingExtra) DoSomethingExtra(p); } public virtual void DoSomethingExtra(object p) { // Empty in base } } class ADerived { public override void DoSomethingExtra(object p) { p.ProcessMore(); } public override bool ShouldDoSomethingExtra { get { return true; } } }
但是,这个解决方案有点脆弱,因为派生类在重写方法时可能会忘记覆盖属性。 我认为有一个无所事事的基础实现是最简单的方法。
这是获得所需内容的最简单方法:
var isDerived = typeof(ADerived).GetMember("DoSomethingExtra", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly).Length == 0;
更新: 此处提供的链接比必要的更详细,但也不完整。 上面的版本也适用于受保护的方法和虚拟属性(这就是为什么你使用GetMember
而不是更严格的GetMethod
),链接地址都不是。
上述就是C#学习教程:如何检测是否在c#中重写了虚方法分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/984805.html