抑制或避免警告CA2214

时间:2014-09-10 12:35:00

标签: c# fxcop

我有一种情况,我从我收到的数据创建一个名为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
    }
}

1 个答案:

答案 0 :(得分:2)

根据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 /特殊值)这是方法即使它更冗长,我也更喜欢。