如何在丢失范围之前修复CA Dispose对象?

时间:2015-11-24 11:44:02

标签: c#

CA会抛出以下消息:

CA2000 Dispose objects before losing scope.
In method 'GetMatchingJobsDeferred(BackgroundJobSearchParameters)',
object '<>g__initLocal0' is not disposed along all exception paths.
Call System.IDisposable.Dispose on object '<>g__initLocal0' before 
all references to it are out of scope.

我有一次性类型CompositeCollection

public sealed class CompositeCollection<T> : IEnumerable<T>, IDisposable
{
    private readonly List<IEnumerable<T>> _enumerables = new List<IEnumerable<T>>();
    private readonly List<IDisposable> _disposables = new List<IDisposable>();

    public void Add(IEnumerable<T> enumerable)
    {
        _enumerables.Add(enumerable);
    }

    public void Add(IDeferredResultCollection<T> deferredResultCollection)
    {
        _enumerables.Add(deferredResultCollection);
        _disposables.Add(deferredResultCollection);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _enumerables.Aggregate((results, enumerable) => results.Concat(enumerable)).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Dispose()
    {
        foreach (var item in _disposables)
        {
            item.Dispose();
        }
    }
}

我是如何使用它的:

public IDeferredResultCollection<BackgroundJobInfoLight> GetMatchingJobsDeferred(BackgroundJobSearchParameters jobSearchParameters)
{
    var memoryLocatedJobs = GetInMemoryJobs(jobSearchParameters);
    var databaseLocatedJobs = GetInDatabaseJobsDeferred(jobSearchParameters, memoryLocatedJobs);

    return new CompositeCollection<BackgroundJobInfoLight>
    {
        memoryLocatedJobs,
        databaseLocatedJobs
    };
}

调用return语句时出现异常。 如何解决?

我添加try catch并且它没有帮助

 public IDeferredResultCollection<BackgroundJobInfoLight> GetMatchingJobsDeferred(BackgroundJobSearchParameters jobSearchParameters)
    {
        CompositeCollection<BackgroundJobInfoLight> deferredJobs = null;
        DeferredResultCollection<BackgroundJobInfoLight> databaseLocatedJobs = null;
        try
        {
            var memoryLocatedJobs = GetInMemoryJobs(jobSearchParameters);
            databaseLocatedJobs = GetInDatabaseJobsDeferred(jobSearchParameters, memoryLocatedJobs);

            deferredJobs = new CompositeCollection<BackgroundJobInfoLight> { memoryLocatedJobs, databaseLocatedJobs };
            return deferredJobs;
        }
        catch
        {
            if (databaseLocatedJobs != null)
            {
                databaseLocatedJobs.Dispose();
            }

            if (deferredJobs != null)
            {
                deferredJobs.Dispose();
            }

            throw;
        }
    }

2 个答案:

答案 0 :(得分:2)

返回一次性对象时,调用者代码应负责Dispose对象。如果在方法本身内部调用Disposed,则被处置对象将返回调用方法,(将不会有任何用途)。

在这种情况下,可以安全地压制警告。

但是如果此方法发生异常怎么办?

  

如果一次性物品没有明确处理   对它的引用超出了范围,该对象将被置于某些位置   垃圾收集器运行终结器时的不确定时间   物体。因为可能会发生可能阻止的异常事件   从运行的对象的终结器,对象应该是   明确地代替了。 MSDN

因此,如果您预计方法中存在任何异常,则应在try...catch块和catch块中使用此代码,您应调用Dispose()检查对象是否为空。

如果您没有返回IDisposable,则可以使用using语句或try...finally并在finally

中调用dispose

答案 1 :(得分:0)

为什么要将项目保存到不同的列表变量中?它可能与您的问题有关。保持DRY将它们存储在一个列表中,并安全地转换为您要查找的内容。

IDisposable myDispType = myEnumarableType as IDisposable;
If (myDispType != null)
    {//your logic here}