我试图在没有压制它的情况下处理这个警告。称之为个人挑战。
CA2000 在方法“
CreateAndUse
”中,在对所有对它的引用超出范围之前,在对象'new Project()'上调用System.IDisposable.Dispose。
在任意IDisposable
类上假设Project
接口。
public void CreateAndUse()
{
var instances = new Project().Using(_ => _.LoadItems());
}
鉴于扩展方法:
public static TR Using<T, TR>(this T instance, Func<T, TR> expression)
where T : IDisposable
{
using (instance)
return expression(instance);
}
当然,智能编译器应该能够正确分析它吗? 我想我错过了什么......
答案 0 :(得分:1)
CA2000发生的原因很简单:您引用了IDisposable
方法中尚未处理的CreateAndUse()
。
您的扩展方法处理您的对象这一事实无关紧要。代码分析器不能假设在扩展方法完成时保证实例被丢弃。如果您最终在其using
块之外的扩展方法中使用该对象执行其他操作,该怎么办?如果其他东西导致异常(使using
块无法访问)怎么办?然后突然间你有一个不安的物体。这就是CA2000试图防范的问题。如果不出意外,代码分析器足够聪明,可以预测代码可能失败的所有其他方式。
You can choose to suppress this warning如果您可以保证您的扩展方法不会对IDisposable
块之外的using
执行任何操作,那么文档中的几次之一就可以禁止此类一个警告。另一方面,在不抑制CA2000的情况下处理CA2000的最佳方法是防止它首先发生。而 的最佳方法是直接使用using
的方式:
public void CreateAndUse()
{
List<Item> instances;
using (var p = new Project())
instances = p.LoadItems();
}
如您所见,Project
的范围缩小到只有一个using
块。相当清晰。正如jgauffin所说,不需要额外的间接层。
答案 1 :(得分:1)
你实际问的一个问题是:
当然,智能编译器应该能够正确分析它吗?
这显示了一个根本的误解。 CA2000不是编译器问题。这是一个代码分析问题,它与编译器完全分开。不,它不是“非常”聪明。所以,不 - 编译器在这里什么都不做,因为编译器没有参与其中。
处理此CA的正确方法是查看它,确定它是否相关,然后可能在方法上对其进行抑制。
原因?
虽然创建对象通常是一个错误,但有时它是预期的功能。如果返回的对象已经被处理掉,那么工厂方法(GetDatabaseConnection())将完全没用。
但那些是“边缘”案件 - 程序员在看到警告后可以决定。这就是方法级别抑制的目的。
有关此案例的类似(但不完全相同)示例,请参阅How to get rid of CA2000 warning when ownership is transferred?。