异常过滤器触发 CA2202?

Posted

技术标签:

【中文标题】异常过滤器触发 CA2202?【英文标题】:Exception filter triggers CA2202? 【发布时间】:2016-02-04 14:33:46 【问题描述】:

我有一个函数,归结为如下所示:

public static string Merge(string xml1, string xml2)

   try
   
      var doc1 = XDocument.Load(new StringReader(xml1));
      var doc2 = XDocument.Load(new StringReader(xml2));

      // these "die" by throwing InvalidOperationException
      var root1 = GetElementOrDie(doc1, Names.RootElementName);
      var root2 = GetElementOrDie(doc2, Names.RootElementName);

      foreach (var element in root2.Elements())
         root1.Add(element);

      return doc1.ToString();
   
   catch (Exception e) when (!(e is InvalidOperationException))
   
      throw new InvalidOperationException(e.Message, e);
   

在 Visual Studio 2015 下,这会生成代码分析警告 CA2202:

Object 'root2.Elements().GetEnumerator()' 可以配置多个 一次在方法“XmlProcessor.Merge(string, string)”中。避免 生成一个您不应该调用的 System.ObjectDisposedException 对一个对象进行多次处理。

如果我删除 when 子句,警告就会消失。

这里发生了什么?警告我对吗?

供参考:

private static XElement GetElementOrDie(XContainer container, XName elementName)

   var element = container.Element(elementName);
   if (element == null)
      throw new InvalidOperationException();
   return element;

【问题讨论】:

这看起来更像是代码分析的问题。我宁愿忽略警告。 我还看到 CA 错误地抱怨在使用像 disposable?.Dispose(); 这样的空条件运算符时没有释放对象 【参考方案1】:

我认为这是代码分析的问题,我会压制它。如果我将循环从:

foreach (var element in root2.Elements())
   root1.Add(element);

为此公开它明确抱怨的枚举器:

var enumerator = root2.Elements().GetEnumerator();
while (enumerator.MoveNext())

    XElement item = enumerator.Current;
    root1.Add(item);

然后CA2202 不再抛出,即使when 过滤器在异常中。

【讨论】:

我怀疑你是对的,但由于 Dispose 不再被枚举器调用,因此更改停止警告也就不足为奇了。我认为要明确回答这个问题,需要检查反汇编并确认没有通过代码的路径会导致Dispose 被多次调用。使用 LinqPad 快速检查显示只生成了一个调用,但我不足以成为 IL 专家,无法确保没有导致该指令被多次执行的跳转或循环。 也就是说,我在第二个版本中遇到的唯一CA2000: Dispose objects before losing scope 错误仍在您的StringReaders 上。

以上是关于异常过滤器触发 CA2202?的主要内容,如果未能解决你的问题,请参考以下文章

代码分析规则 CA2000 / CA2202

AuthenticationEntryPoint导致登录页面异常

MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage

您不应在一个对象上多次调用 Dispose(CA2202)[重复]

WPF代码分析:CA2202 Do not dispose objects multiple timesObject

空条件运算符和 CA2202:不要多次处理对象