English 中文(简体)
便于分析的处置物体的方法
原标题:The Code Analysis-friendly way to dispose of objects

作为我们2010年视觉演播室(主要是C# 4.0)发展标准的一部分,我们改变了《守则分析》。 在我审查最近提交的新项目守则时,我看到了一个避风港。

CA2000 : Microsoft.Reliability: In method XYZ , object ABC is not disposed along all exception paths. Call System.IDisposable.Dispose on object ABC before all references to it are out of scope.

警告。 问题在于,我似乎没有消除这些警告——我花了几个小时时间鼓励网络并尝试我能够做的一切。

首先,让我清楚地看到,我并不是说要简单地使用块来妥善处理地方变量——这不是一个问题。 就我而言,当物体通过方法归还或按照方法分配给另一物体时,这些警告就出现。

此处是包含四项此类警告的法典样本:

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条款(here)所述两种方法进行重新评价,但警告仍然出现。

UPDATE I should note that both SomeObject and SomeOtherObject implement IDisposable.

Also, while object initializers may be a component of the problem, keep in mind that the initializers are isolated to the two private methods and have nothing to do with the warnings in MainMethod.

Can anyone show me how to properly implement these methods to eliminate the CA2000 warnings?

最佳回答

The problem that is being detected by CA2000 in this case is that a disposable instance may be "orphaned" if an exception occurs before it is passed out of the method. For example, a "correct" implementation of CreateFirstObject would look something like the following:

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

    return theObject;
}

Given what you have described concerning your desired behaviour for MainMethod, its "correct" implementation might look something like this:

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的警告?

In the mentioned link it is basically stated to add the object to a collection implementing ICollection<T>, but I haven t tested that.

What happens if you wrap the returned objects in main in a using block, or implement a finally to dispose of the objects?

Do the SomeOtherObjects need to implement IDisposable?

所需要的是实施类似于“使用”组的模式,但在将成功归还的情形下排除处置该物体。 妮科尔·卡利诺伊乌提出的办法是合理的,但我更愿意避免只出现一些可能无法解决的例外情况。 鉴于C#语言的局限性,我倾向于采用先入为主的高压旗,然后有“最终”的区块,如果未被征召,则予以处置。

如果一个班子将包含许多可移入的物体,并且一旦施工完成,这些物体将固定下来,那么界定一个可识别的经理类别可能是有益的,该类别将包含一份可识别物体清单。 1. 贵阶层的构造者是否接受可处置的Manager物体作为参数,并将其所制造的所有物体列入由此产生的清单(可能有助于您的班级采用一种检查方法):

T regDisposable<T>RegDispose(T newThing) where T:IDisposable
{
  myDisposableManager.Add(newThing);
  return newThing;
}

在我的可支配的Manager被初步采用后,简单地说:。 这种模式将带来两项重大利益:

  1. All the main class would have to do in its Dispose implementation would be `if (myDisposableManager != null) myDisposableManager.Dispose();` The act of setting an IDisposable object in the constructor (using RegDispose) would also provide for its cleanup.
  2. The code calling the constructor for the main object could, if the constructor throws an exception, call the Dispose method on the DisposableManager object it had created and passed in. This would ensure timely cleanup of the partially-created object, something which is otherwise all but impossible.

在 vb中,基级建筑商有可能将建筑参数作为可供外地初始器使用的一个领域。 因此,人们可以在野心初始器和明确建筑商中 use然使用“RegDispose”模式。 C#无法做到。 有可能为此目的使用[现成的]领域,但需要谨慎行事,以确保所建立的任何此类领域也不受干扰。 一个建筑商从像一个透水池的透镜中抽出,可能会造成记忆泄。 此外,不能像正常的一样,几乎有效地进入read地,我不知道在C#中的任何方式,以避免不得不为每个已登记的可识别物体重新划定地表。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签