【问题标题】:C# Inheritance best-practiceC# 继承最佳实践
【发布时间】:2011-12-14 11:05:17
【问题描述】:

我有一个名为BaseView 的普通类,它带有一个虚拟方法DisplayView。此方法调用GetHeaderGetBody 虚拟方法来获取页面的内容。然后,我将创建一个继承自BaseView 的类,并覆盖需要以不同于基类的方式显示内容的方法。

我的问题是,虽然这很好用,但在运行代码分析时,我被警告不要直接调用虚函数。

我是否应该在基类之上创建另一个类层来覆盖虚函数并仅从其继承?

直接使用虚方法有什么缺点?

编辑:警告是:

CA2214 : Microsoft.Usage : xxx 包含一个调用链,导致 调用类定义的虚方法。查看以下内容 意外后果的调用堆栈

【问题讨论】:

  • 请显示准确的警告信息
  • 在派生类方法实现中添加 new/override 关键字,这个警告可能会消失。
  • 如果你从构造函数调用你的虚拟方法,检查这个问题:stackoverflow.com/questions/448258/…
  • @Maheep 使用new关键字不会覆盖基类方法,只是简单的隐藏基类实现
  • 代码分析消息号是多少(应该叫CA2214之类的)?

标签: c# inheritance


【解决方案1】:

我认为问题在于DisplayView 是虚拟的,它正在调用虚拟方法。在大多数情况下,最终方法调用虚方法作为改变行为的一种手段,例如在策略模式中。如果 final 方法调用了虚方法,编译器知道虚方法在所有派生类中都会被调用,因此虚方法存在是有效的。

您从 virtual 调用 virtual 的事实意味着您的设计可能会受到质疑:如果 DisplayView 是虚拟的,则另一个实现可能会覆盖它。当前实现调用虚拟GetHeader,但派生类可能不会。因此它不能保证GetHeader 不是死代码。

这可能是 FxCop 引起您注意的地方。它想知道,如果您在基类中定义了一个虚拟方法(在这种情况下为GetHeader),那么所有派生实现都将使用它。

我会专注于使DisplayView 最终确定,或者从这个角度评估您的设计。

【讨论】:

  • 我用FxCop用了很久,规则里面有一些很有意思的想法,大部分我都勉强同意了!
  • 但是msdn doc on CA2214 说如果不从构造函数调用虚方法应该没问题,或者至少我是这样理解的
  • 有趣。问题没有提到这是从构造函数中调用的。是吗?
  • 是的,OP提到他正在从另一个虚拟方法 DisplayView调用虚拟方法GetHeaderGetBody,所以我不明白这是怎么回事规则在这里适用
  • 预期行为是虚拟 GetHeader 方法可能返回一个包含视图名称的简单字符串。在某些情况下,可能需要更详细的标头,然后派生类将覆盖 GetHeader。虚拟方法 DisplayView(从派生类调用)然后将调用 GetHeader 的重写方法。
猜你喜欢
  • 2021-06-24
  • 2016-07-05
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
相关资源
最近更新 更多