6

CA2000 是关于 IDisposable 接口的警告:

CA2000:Microsoft.Reliability:在方法“ImportProcessor.GetContext(string)”中,在对对象“c”的所有引用超出范围之前调用 System.IDisposable.Dispose。

我的方法用于存储上下文缓存,如下所示:

public class RegionContext : IDisposable { /* Implement Dispose() here */ } 

private Dictionary<string, RegionContext> contextCache = new ..... ();

public RegionContext GetContext(string regionCode)
{
    RegionContext rc = null;

    if (!this.contextCache.TryGetValue(regionCode.ToUpper(), out rc))
    {
        rc = new RegionContext(regionCode);
        this.contextCache.Add(regionCode.ToUpper(), rc);
    }

    return rc;
}

您将在哪里使用using()修复此编译器警告的语句?

我的外部类实际上会contextCache在它自己的实现中迭代和处理内容。我应该压制它,还是有办法正确摆脱这个警告?

4

3 回答 3

12

只要您有一个 IDisposable 的返回值并且不处理该方法引发异常的情况,就会出现此 CA2000 警告。在这种情况下,调用者将无法获得您对象的有效实例,因此无法处置它。因此你必须这样做。

我假设如果您成功地将其从缓存中拉出,您将不想处置该对象。在这种情况下,您需要执行以下操作以确保您可能在本地创建的对象在所有情况下都被释放:

public RegionContext GetContext(string regionCode)
{
    RegionContext temp = null;
    RegionContext rc = null;

    try
    {
        if (!this.contextCache.TryGetValue(regionCode.ToUpper(), out rc))
        {
            temp = new RegionContext(regionCode);
            this.contextCache.Add(regionCode.ToUpper(), temp);

            rc = temp;
            temp = null;
        }

        return rc;
    }
    finally 
    {
        if ( temp != null ) 
        {
             temp.Dispose();
        }
    }
}
于 2011-07-14T14:12:23.627 回答
6

CA2000 在这里抱怨的是,如果在尝试将其添加到缓存中时出现异常,该变量可能会在未处理状态下“孤立”。为了彻底解决这个问题,您可以添加一个 try/catch 如下(该newContext变量仅用于 CA2000 可以检测到修复):

public RegionContext GetContext(string regionCode)
{
    RegionContext rc = null;
    if (!this.contextCache.TryGetValue(regionCode.ToUpper(), out rc))
    {
        RegionContext newContext = new RegionContext(regionCode);
        try
        {
            this.contextCache.Add(regionCode.ToUpper(), newContext);
        }
        catch
        {
            newContext.Dispose();
            throw;
        }

        rc = newContext;
    }

    return rc;
}

就个人而言,在大多数情况下,我觉得这种事情有点荒谬,但 ymmv ......

于 2011-07-14T12:43:33.157 回答
0

转换为 VB.Net 时,Michael 的解决方案似乎不起作用。以下两个功能在VS 2017下测试:

    Public Function OpenStream(ByVal filePathName As String) As System.IO.FileStream
        Dim fileStream As System.IO.FileStream = Nothing
        Dim tempFileStream As System.IO.FileStream = Nothing
        If Not String.IsNullOrWhiteSpace(filePathName) Then
            Try
                tempFileStream = New System.IO.FileStream(filePathName, System.IO.FileMode.Open, System.IO.FileAccess.Read)
                fileStream = tempFileStream
            Catch
                tempFileStream?.Dispose()
                Throw
            End Try
        End If
        Return fileStream
    End Function

    Public Function OpenReader(ByVal filePathName As String) As System.IO.BinaryReader
        If String.IsNullOrWhiteSpace(filePathName) Then Throw New ArgumentNullException(NameOf(filePathName))
        If Not System.IO.File.Exists(filePathName) Then Throw New System.IO.FileNotFoundException("Failed opening a binary reader -- file not found.", filePathName)
        Dim tempReader As System.IO.BinaryReader = Nothing
        Dim reader As System.IO.BinaryReader = Nothing
        Dim stream As IO.FileStream = Nothing
        Try
            stream = Methods.OpenStream(filePathName)
            tempReader = New System.IO.BinaryReader(stream)
            reader = tempReader
        Catch
            stream?.Dispose()
            tempReader?.Dispose()
            Throw
        End Try
        Return reader
    End Function
于 2017-04-25T18:10:18.460 回答