处置或不处置 (CA2000)
我正在旧项目上启用代码分析。大多数评论我都能理解,但是CA2000:在失去范围之前释放对象 很难做对。
例如,来自 ASP.Net 页面的以下代码:
private void BuildTable()
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
tr.Cells.Add(td);
// add some controls to 'td'
theTable.Rows.Insert(0, tr);
// 'theTable' is an HtmlTable control on the page
}
提供 CA 消息:
CA2000:Microsoft.Reliability:在方法“BuildTable()”中,在对象“tr”的所有引用超出范围之前调用 System.IDisposable.Dispose。
CA2000:Microsoft.Reliability:在方法“BuildTable()”中,对象“td”未沿着所有异常路径进行处理。在对对象“td”的所有引用超出范围之前,对对象“td”调用 System.IDisposable.Dispose。 (以及有关添加到该“td”的控件的类似消息。)
我可以解决第二个问题:
private void BuildTable()
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
try
{
tr.Cells.Add(td);
// add some controls to 'td'
td = null; // this line is only reached when there were no exceptions
}
finally
{
// only dispose if there were problems ('exception path')
if (td != null) td.Dispose();
}
theTable.Rows.Insert(0, tr);
}
但我认为不可能解决有关“tr”的消息。我无法处理它,因为在方法退出后仍然需要它。
或者我错过了什么?
顺便说一句:将 theTable.Rows.Insert
更改为 theTable.Rows.Add
会将 CA 消息更改为“未沿所有异常路径进行处理” '
I'm switching on Code Analysis on an older project. Most remarks that result I can understand, but the CA2000: Dispose objects before losing scope is hard to get right.
For instance, this code from an ASP.Net page:
private void BuildTable()
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
tr.Cells.Add(td);
// add some controls to 'td'
theTable.Rows.Insert(0, tr);
// 'theTable' is an HtmlTable control on the page
}
Gives CA messages:
CA2000 : Microsoft.Reliability : In method 'BuildTable()', call System.IDisposable.Dispose on object 'tr' before all references to it are out of scope.
CA2000 : Microsoft.Reliability : In method 'BuildTable()', object 'td' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'td' before all references to it are out of scope.
(and similar messages about the controls that are added to that 'td'.)
I can resolve the second problem:
private void BuildTable()
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
try
{
tr.Cells.Add(td);
// add some controls to 'td'
td = null; // this line is only reached when there were no exceptions
}
finally
{
// only dispose if there were problems ('exception path')
if (td != null) td.Dispose();
}
theTable.Rows.Insert(0, tr);
}
But I don't think it is possible to resolve the message about the 'tr'. I can't Dispose of that, because it's still needed after the method has exited.
Or did I miss something?
By the way: changing that theTable.Rows.Insert
into theTable.Rows.Add
changes the CA message to 'not disposed along all exception paths'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
代码分析无法完全理解您的代码,并且仅在您创建似乎未处理的一次性对象时发出警告。在您的情况下,您应该关闭警告,因为在离开方法之前不应释放该对象。您可以通过自定义代码分析规则集来关闭整个项目的警告,也可以在明显表明代码分析错误的每个具有此警告的方法上关闭警告。
也就是说,我建议您在处理
IDisposable
对象时使用using
构造:除了这段代码是无意义的,因为您不想处置该行并且您刚刚添加到表格中的单元格。
The code analysis is unable to completely understand your code and simply warns if you create a disposable object that seems to not be disposed. In your case you should turn off the warning because the object should not be disposed before leaving the method. You can turn warnings off either for the entire project by customizing the code analysis rule set or on each method having this warning where it is obvious that the code analysis is wrong.
That said, I recommend that you use the
using
construct when dealing withIDisposable
objects:Except this code is nonsense as you don't want to dispose the row and cell you just added to the table.
我认为您刚刚表明 CA2000 规则在大多数代码库上不是很有用
据我所知,
由于上述两种情况在普通代码中都很常见,因此我认为 CA2000 规则对大多数代码库没有价值 - 有如此多的误报当这是一个真正的问题时,很可能有五十分之一的情况会被遗漏。
I think you have just shown that the CA2000 rule is not very useful on most code bases
As far as I know,
As both of the above is very common in normal code, I don’t see the CA2000 rule to be of value to most code bases – there are so many false positives you are very likely to miss in 1 in 50 cases when it is a real problem.
这段代码将消除这两个警告
(我使用 using(HtmlTable) 来模拟您的全局 HtmlTable 成员...):
但我认为您会考虑使用使用子函数的方法来使代码更清晰:
this code will get rid of both warnings
(I use a using(HtmlTable) to simulate your global HtmlTable member...):
but I think you will consider using an approach that uses subfunctions to make the code more clear:
创建控件后、对控件执行任何操作之前,立即将控件添加到集合中。
由于创建控件和将控件添加/插入到集合之间不会出现异常,因此不需要 try/catch。当控件添加到集合后发生异常时,页面将处理它。您不会通过这种方式获得 CA2000。
Add the control to the collection directly after creating it, but before you do anything with the control.
As there can't be an exception between creating and adding/inserting the control to the collection there is no need for try/catch. When an exception occurs after the control is added to the collection the page will dispose of it. You won't get the CA2000 this way.
如果您认为代码分析是错误的(发生在我身上,它要求为未实现 IDisposable 的对象调用 Dispose)或者您认为没有必要 Dispose 该对象,您可以随时抑制该消息,例如这。
In case you think that Code Analysis is wrong (happened to me that it asked to call Dispose for an object that didn't implement IDisposable) or you don't feel it is necessary to Dispose that object, you can always suppress that message like this.