MSOCAF验证 - 不要在构造函数中调用可覆盖的方法

时间:2014-11-20 09:26:28

标签: c# constructor code-analysis

我在MSOCAF中有这个错误:

  
    

'ExcelChart.ExcelChart(ExcelDrawings,XmlNode,Uri,PackagePart,XmlDocument,XmlNode)'包含一个调用链,该调用链导致调用     由类定义的虚方法。查看以下调用堆栈     意外后果:

  
     

ExcelChart..ctor(ExcelDrawings,XmlNode,Uri,PackagePart,   XmlDocument,XmlNode)ExcelChart.InitChartLoad(ExcelDrawings,   XmlNode):Voi ExcelChart.GetChartType(String):eChartType

构造函数:

internal ExcelChart(ExcelDrawings drawings, XmlNode node, Uri uriChart, PackagePart part, XmlDocument chartXml, XmlNode chartNode) :
       base(drawings, node, "xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/@name")
   {
       UriChart = uriChart;
       Part = part;
       ChartXml = chartXml;
       _chartNode = chartNode;
       InitChartLoad(drawings, chartNode);
       ChartType = GetChartType(chartNode.LocalName);
   }

错误的一行:

XmlNode _chartNode = null;
    internal XmlNode ChartNode
    {
        get
        {
            return _chartNode;
        }
    }

这两种方法:

private void InitChartLoad(ExcelDrawings drawings, XmlNode chartNode)
   {
       //SetChartType();
       bool isPivot = false;
       Init(drawings, chartNode);
       _chartSeries = new ExcelChartSeries(this, drawings.NameSpaceManager, _chartNode, isPivot /*ChartXml.SelectSingleNode(_chartPath, drawings.NameSpaceManager)*/);
       LoadAxis();
   }

internal virtual eChartType GetChartType(string name)
   {

       switch (name)
       {
           case "area3DChart":
               if(Grouping==eGrouping.Stacked)
               {
                   return eChartType.AreaStacked3D;
               }
               else if (Grouping == eGrouping.PercentStacked)
               {
                   return eChartType.AreaStacked1003D;
               }
               else
               {
                   return eChartType.Area3D;
               }
           case "areaChart":
               if (Grouping == eGrouping.Stacked)
               {
                   return eChartType.AreaStacked;
               }
               else if (Grouping == eGrouping.PercentStacked)
               {
                   return eChartType.AreaStacked100;
               }
               else
               {
                   return eChartType.Area;
               }
           case "bubbleChart":
               return eChartType.Bubble;
           case "doughnutChart":
               return eChartType.Doughnut;
           case "pie3DChart":
               return eChartType.Pie3D;
           case "pieChart":
               return eChartType.Pie;
           case "radarChart":
               return eChartType.Radar;
           case "scatterChart":
               return eChartType.XYScatter;
           case "surface3DChart":
           case "surfaceChart":
               return eChartType.Surface;
           case "stockChart":
               return eChartType.StockHLC;
           default:
               return 0;
       }           
   }

我在CodePlex中找到了这段代码,我尝试解决MSOCAF返回的所有错误

1 个答案:

答案 0 :(得分:0)

构造函数ExcelChart()调用虚方法GetChartType()。派生类可以覆盖此方法,并使用在基类(ExcelChart)执行其构造函数时不存在或未初始化的数据。基类的实现者无法知道或防止后来从他或她的类派生的代码,并且从中派生的人可能不知道基本ctor调用他或她真正的虚拟方法想要覆盖。

这就是编码指南经常禁止在ctors中调用虚拟方法的原因。

请注意,虚拟方法的这种实现不同于C ++,其中调用那些在ctor执行的类的vtable中的虚拟方法;也就是说,在嵌套的ctors中,每个ctor可以调用不同版本的"相同的"虚方法。相比之下,在C#中,总是"最衍生的"调用继承链中的实现。虽然这可能更简单,更可预测,但它对于继承的概念有点反对范式,并导致访问数据的危险,基类没有 知道。