C# 继承最佳实践
Posted
技术标签:
【中文标题】C# 继承最佳实践【英文标题】:C# Inheritance best-practice 【发布时间】:2011-12-14 11:05:17 【问题描述】:我有一个名为BaseView
的普通类,它带有一个虚拟方法DisplayView
。此方法调用GetHeader
和GetBody
虚拟方法来获取页面的内容。然后,我将创建一个继承自BaseView
的类,并覆盖需要以不同于基类的方式显示内容的方法。
我的问题是,虽然这很好用,但在运行代码分析时,我被警告不要直接调用虚函数。
我是否应该在基类之上创建另一个类层来覆盖虚函数并仅从其继承?
直接使用虚方法有什么缺点?
编辑:警告是:
CA2214 : Microsoft.Usage : xxx 包含一个调用链,导致 调用类定义的虚方法。查看以下内容 意外后果的调用堆栈
【问题讨论】:
请显示准确的警告信息 在派生类方法实现中添加 new/override 关键字,这个警告可能会消失。 如果你从构造函数调用你的虚拟方法,检查这个问题:***.com/questions/448258/… @Maheep 使用new关键字不会覆盖基类方法,只是简单的隐藏基类实现 代码分析消息号是多少(应该叫CA2214之类的)? 【参考方案1】:我认为问题在于DisplayView
是虚拟的,它正在调用虚拟方法。在大多数情况下,最终方法调用虚方法作为改变行为的一种手段,例如在策略模式中。如果 final 方法调用了虚方法,编译器知道虚方法在所有派生类中都会被调用,因此虚方法存在是有效的。
您从 virtual 调用 virtual 的事实意味着您的设计可能会受到质疑:如果 DisplayView
是虚拟的,则另一个实现可能会覆盖它。当前实现调用虚拟GetHeader
,但派生类可能不会。因此它不能保证GetHeader
不是死代码。
这可能是 FxCop 引起您注意的地方。它想知道,如果您在基类中定义了一个虚拟方法(在这种情况下为GetHeader
),那么所有派生实现都将使用它。
我会专注于使DisplayView
最终确定,或者从这个角度评估您的设计。
【讨论】:
我用FxCop用了很久,规则里面有一些很有意思的想法,大部分我都勉强同意了! 但是msdn doc on CA2214 说如果不从构造函数调用虚方法应该没问题,或者至少我是这样理解的 有趣。问题没有提到这是从构造函数中调用的。是吗? 是的,OP提到他正在从另一个虚拟方法DisplayView
调用虚拟方法GetHeader
和GetBody
,所以我不明白这是怎么回事规则在这里适用
预期行为是虚拟 GetHeader 方法可能返回一个包含视图名称的简单字符串。在某些情况下,可能需要更详细的标头,然后派生类将覆盖 GetHeader。虚拟方法 DisplayView(从派生类调用)然后将调用 GetHeader 的重写方法。以上是关于C# 继承最佳实践的主要内容,如果未能解决你的问题,请参考以下文章