CA2000是一个关于IDisposable接口的警告:
CA2000: Microsoft。可靠性:` ImportProcessor.GetContext(string) `,调用System.IDisposable.Dispose
在对象'c'的所有引用都超出作用域之前。
我的方法用于存储上下文缓存,如下所示:
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
中的内容。我是否应该抑制它,或者是否有一种方法可以正确地摆脱这个警告?
只要您有一个不可处置的返回值,并且不处理方法抛出异常的情况,就会出现这个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();
}
}
}
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;
}
就我个人而言,我觉得这种事情在大多数情况下有点荒谬,但是,嗯……
Michael的解决方案在转换为VB.Net时似乎不起作用。在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