CA2000是如何工作的,我试图解决它

时间:2016-05-13 07:12:53

标签: c#

我试图在没有压制它的情况下处理这个警告。称之为个人挑战。

  

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);
}

当然,智能编译器应该能够正确分析它吗? 我想我错过了什么......

2 个答案:

答案 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?