抑制或避免警告CA2214
本文关键字:警告 CA2214 | 更新日期: 2023-09-27 18:21:32
我有一种情况,我从收到的数据中创建了一个名为EntryEvent
的对象。必须对该数据进行解析。基本事件应该启动对通过构造函数接收并提供给对象的数据的解析。子类型知道如何解析特定的数据集。现在,当编译所述代码时,我得到警告CA2214,它包含对虚拟方法的调用链。虽然产生不可预见的后果可能很糟糕,但我不知道如何获得所需的行为:解析接收到的事件,而不必从外部调用额外的"Parse"方法。
有问题的代码是:
public abstract class BaseEvent
{
protected BaseEvent(object stuff)
{
this.ParseEvent();
}
protected abstract void ParseEvent();
}
public class EntryEvent : BaseEvent
{
public EntryEvent( object stuff )
: base( stuff )
{
}
protected override void ParseEvent()
{
// Parse event
}
}
根据MSDN(重点是我的):
当调用虚拟方法时,直到运行时才会选择执行该方法的实际类型。当构造函数调用虚拟方法时,调用该方法的实例的构造函数可能尚未执行。
所以在我看来,你有这些选择(至少):
1) 不要禁用该警告,而是为记录其预期行为的特定类抑制该消息(假设您在处理此类场景时格外小心)。如果它被限制在一个非常可控的环境中的几个类,那也没那么糟糕(毕竟…警告不是错误,它们可能会被忽略)。
2) 从基类构造函数中删除该虚拟方法调用,但保留abstract
方法声明。开发人员必须实现这样的方法,并且要在构造函数中调用它,他们需要将自己的类标记为sealed
。最后在类/方法文档中添加一个地方,即该方法必须在其构造函数内调用,并且其类必须是sealed
才能调用。它们可以忘记调用,但您可以在访问属性或方法时添加(对于DEBUG
构建)检查(例如,作为类接口的一部分,强制设置特定标志)。如果他们忘记设置标志或忘记调用方法,则将引发异常("此对象尚未构建,必须在派生类构造函数中调用ParseEvent()。")。
我不太喜欢这个方法,因为它增加了额外的复杂性,但如果你的类层次结构太大(然后你觉得你不能使用#1)或懒惰初始化(如#3所述)不适用,那么它可能是一个工作的解决方案。我还考虑更改设计,引入一个工厂方法,该方法将为每个完全构建的对象调用ParseEvent()。
3) 稍微改变一下你的设计:将解析推迟到需要的时候。例如:
public abstract class BaseEvent
{
public DateTime TimeStamp
{
get
{
if (_timestamp == null)
ParseEvent();
return _timestamp.Value;
}
protected set { _timestamp = value; }
}
protected BaseEvent(object stuff)
{
}
protected abstract void ParseEvent();
private DateTime? _timestamp;
}
最后一个示例仅用于说明目的,您可能希望使用Lazy<T>
以更精确、清晰和线程安全的方式执行相同的任务。当然,在现实中,你会有更多的字段/属性,解析可能会在一个镜头中提供所有值(然后你只需要一个标志,不需要在每个字段上使用Nullable
/特殊值)这是我更喜欢的方法,即使它更详细。