友好的方式来处理物体

作为Visual Studio 2010(主要是C#4.0)开发标准的一部分,我们开启了代码分析。 在我审查最近为新项目提交的代码时,我看到了很多

CA2000:Microsoft.Reliability:在'XYZ'方法中,对象'ABC'不是沿着所有异常路径处理的。 调用System.IDisposable.Dispose对象'ABC'之前,所有对它的引用超出范围。

警告。 问题是,我没有做任何事情似乎可以消除警告 - 我花了几个小时在网上冲浪,并尽我所能地尝试。

首先,让我清楚,我不是在谈论如何简单地使用块来恰当地处理局部变量 - 这不是问题。 在我的情况下,当对象由方法返回或分配给方法内的另一个对象时,这些警告就会出现。

以下是包含四个此类警告的代码示例:

public void MainMethod()
{
    var object1 = CreateFirstObject();    // Warning here
    var object2 = CreateSecondObject();   // Warning here

    SomeCollectionProperty.Add(object1);
    SomeCollectionProperty.Add(object2);
}

private SomeObject CreateFirstObject()
{
    var theObject = new SomeObject()      // Warning here
    {
        FirstProperty = "some value",
        // ...
    };

    return theObject;
}

private SomeOtherObject CreateSecondObject()
{
    var theObject = new SomeOtherObject() // Warning here
    {
        FirstProperty = "a different value",
        // ...
    };

    return theObject;
}

我已经评论了警告发生的地方。

我已经尝试重构MSDN文章(此处)中描述的创建方法,但警告仍然出现。

更新我应该注意,SomeObject和SomeOtherObject都实现了IDisposable。

另外,尽管对象初始值设定项可能是问题的一个组成部分,但请记住,初始值设定项被隔离到两个私有方法,并且与MainMethod中的警告无关。

任何人都可以告诉我如何正确实施这些方法来消除CA2000警告?


在这种情况下,CA2000正在检测到的问题是,如果在将异常从方法中移出之前发生异常,则可丢弃实例可能会“孤立”。 例如,CreateFirstObject的“正确”实现看起来如下所示:

private SomeObject CreateFirstObject()
{
    var theObject = new SomeObject();
    try
    {
        theObject.FirstProperty = "some value";
    }
    catch
    {
        theObject.Dispose();
        throw;
    }

    return theObject;
}

根据你所描述的关于MainMethod的期望行为,它的“正确”实现可能看起来像这样:

public void MainMethod()
{
    var object1 = CreateFirstObject();
    try
    {
        SomeCollectionProperty.Add(object1);

        var object2 = CreateSecondObject();
        try
        {
            SomeCollectionProperty.Add(object2);
        }
        catch
        {
            object2.Dispose();
            throw;
        }
    }
    catch
    {
        object1.Dispose();
        SomeCollectionProperty.Remove(object1); // Not supposed to throw if item does not exist in collection.

        throw;
    }
}

摆脱警告的一种方法是在代码中将其抑制:

[SuppressMessage(
    "Microsoft.Reliability",
    "CA2000:DisposeObjectsBeforeLosingScope",
    Justification = "Factory method")]

但这不是问题的真正解决方案

这里介绍一种解决方案:如何在所有权转移后摆脱CA2000警告?

在上面提到的链接中,基本上声明将对象添加到实现ICollection<T>的集合中,但我没有测试过。


如果将返回的对象包装在main块中,或者实现一个finally来处理这些对象,会发生什么?

SomeOtherObjects是否需要实现IDisposable?

链接地址: http://www.djcxy.com/p/63013.html

上一篇: friendly way to dispose of objects

下一篇: Disposing method which returns Timer