C# 继承最佳实践

Posted

技术标签:

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

我有一个名为BaseView 的普通类,它带有一个虚拟方法DisplayView。此方法调用GetHeaderGetBody 虚拟方法来获取页面的内容。然后,我将创建一个继承自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调用虚拟方法GetHeaderGetBody,所以我不明白这是怎么回事规则在这里适用 预期行为是虚拟 GetHeader 方法可能返回一个包含视图名称的简单字符串。在某些情况下,可能需要更详细的标头,然后派生类将覆盖 GetHeader。虚拟方法 DisplayView(从派生类调用)然后将调用 GetHeader 的重写方法。

以上是关于C# 继承最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

结构化存储过程的最佳实践

在 C# 中实现加密和解密的最佳实践 [关闭]

C# 数据连接最佳实践?

关于最佳实践的 C# 神话?

将 SWIG 与 C# 结合使用时的最佳实践是啥?

C#成员变量初始化;最佳实践?