异常过滤器触发 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
错误仍在您的StringReader
s 上。以上是关于异常过滤器触发 CA2202?的主要内容,如果未能解决你的问题,请参考以下文章
AuthenticationEntryPoint导致登录页面异常
MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage
您不应在一个对象上多次调用 Dispose(CA2202)[重复]