【问题标题】:I can't get code analysis rule CA2202 fixed我无法修复代码分析规则 CA2202
【发布时间】:2013-03-27 15:06:21
【问题描述】:

我有一个函数(见下面的代码 sn-p)。

我启用了代码分析,但发现违反 CA2202 规则。

编辑:我在 pdfStamper 上添加了关闭,否则 PDF 将被损坏)

CA2202:不要多次处理对象

方法实现包含可能导致多次调用 IDisposable.Dispose 或 Dispose 等效项的代码路径,例如某些类型上的 Close() 方法,在同一个对象上。

在 CA2202 MSDN 页面 (here) 中,建议的修复不起作用。

如何在不必抑制这种违规的情况下重写代码?

private byte[] DoGenerateFinishedGamePdf(int gameSessionLogId)
{
   var finishedGameCertificatePdfFile = httpServerUtilityWrapper.MapPath(ConfigurationManager.AppSettings["FinishedGameCertificateFile"]);

   var pdfReader = new PdfReader(finishedGameCertificatePdfFile); // note that PdfReader is not IDisposeable

   using (MemoryStream memoryStream = new MemoryStream())
   using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream))
   {
      var fields = pdfStamper.AcroFields;
      fields.SetField("CityName", "It works!");

      pdfReader.Close();

      pdfStamper.FormFlattening = true;
      pdfStamper.FreeTextFlattening = true;
      pdfStamper.Close();

      return memoryStream.ToArray();
   }
}

【问题讨论】:

  • 这很奇怪。我将 using 用于一次性物品,但从未收到 Dispose 警告。您收到的是 memoryStream 还是 pdfStamper?

标签: c# itextsharp code-analysis


【解决方案1】:

啊,大家最喜欢的警告!在这种情况下,MemoryStream.Dispose 是幂等的(当前的实现什么都不做)所以这不是一个真正的问题,但是“修复”如下:

MemoryStream memoryStream = null;
try
{
  memoryStream = new MemoryStream();
  using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream))
  {
    memoryStream = null;

    var fields = pdfStamper.AcroFields;
    fields.SetField("CityName", "It works!");

    pdfReader.Close();

    pdfStamper.FormFlattening = true;
    pdfStamper.FreeTextFlattening = true;
    pdfStamper.Close();

    return memoryStream.ToArray();
  }
}
finally
{
  if (memoryStream != null) memoryStream.Dispose();
}

由于 PdfStamper“拥有”MemoryStream,它会在调用 PdfStamper.Dispose 时将其释放,因此如果我们不释放 PdfStamper,我们只需要在 MemoryStream 上调用 Dispose,这只有在构造PdfStamper 失败。

【讨论】:

  • 代码 sn-p 将无法编译,因为您重新声明了 memorystream。如果我通过删除类型名来解决此问题,我会在第 5 行收到 CA2000 错误:'call System.IDisposable.Dispose on object'memoryStream' before all references are out of scope'....
  • @PatrickPeters 对未编译、复制粘贴错误、答案已更新表示歉意。嗯,上面的代码在我的VS中没有任何警告(VS2012使用.Net 4.5编译器)
  • 我忘记将 pdfStamper = new PdfStamper(pdfReader, memoryStream) 从您的代码示例中放入我的代码中,现在我收到 3(!!) 个警告:一个 CA2000 在 memoryStream 创建时,两个在 finally 块中的每个 Dispose 上都有 CA2202...请注意,我编辑了原始问题,在 pdfStamper 完成其工作后,我在其中添加了一个代码行(带有关闭)。
  • @PatrickPeters 您使用的是哪个编译器?但是,根据 MSDN 上的建议更新答案(再次,在我的机器上不生成任何警告(尽管显然这并不意味着什么,因为上次 sn-p 在你的机器上生成了 3 个!))
  • 我根据您的最新编辑对其进行了更改,但仍然出现 2 个 CA2202 违规。一个内存流,另一个在 pdfStamper,都在 finally 语句的同一行,啊...
【解决方案2】:

发生这种情况是因为 PdfStamper 正在处理流,即使它不应该。它没有创建它,也没有拥有它,因此它没有义务处置它。

您的代码确实创建了流并且它确实拥有它,因此它应该处置它是很自然的。如果 PdfStamper 没有不恰当地处理流,那么您的嵌套使用一切都会好起来的。

您的第一步可能应该是提交错误报告/功能请求,要求删除或至少可以避免流的 PdfStamper 处置。完成此操作后,您可以非常安全地抑制 CA2202 违规,因为 MemoryStream 的双重处置不会产生有害后果。

顺便说一句,PdfStamper.Dispose() 调用 PdfStamper.Close()(至少在 5.4.0 版中),因此您应该能够删除 PdfStamper.Close() 调用。

【讨论】:

    猜你喜欢
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    相关资源
    最近更新 更多