Class 级变量与 CA2000 警告方法的区别
Difference between Class level variable and method for CA2000 Warning
我正在为使用 .net 的 SPA 应用程序开发 Web Api。当我在方法中使用实例化对象时,我收到 CA2000 警告。但是当我在 class 级别声明相同的对象时,CA2000 警告消失了。从下面看,示例 1 给出了 CA2000 警告,而示例 2 没有。为什么?
示例 1-
public class CodeGenAPIController : ApiResponseController
{
NextGenCodeGen.CodeGenerator getEndPoint(TokenManager.TokenData tokenData, int BranchId)
{
NextGenCodeGen.CodeGenerator ret = null;
lock (branchGenLock)
{
if (branchGenerators.ContainsKey(BranchId))
ret = branchGenerators[BranchId];
}
if (ret == null)
{
string services = ConfigurationValuesAPIController.GetBranchProperties(tokenData.DatabaseIdentifier, BranchId).FirstOrDefault(x => x.Key == "AvailableCodeGenServices").Value;
string[] endpoints = services.Split(new char[] { ' ', '.' }, StringSplitOptions.RemoveEmptyEntries);
if (endpoints.Length == 0)
throw new ArgumentOutOfRangeException("AvailableCodeGenServices",
string.Format("There appear to be no Code Generation Services configured for branch {0}", BranchId));
string endpoint = endpoints[0];
if (!endpoint.ToLower().EndsWith(".asmx"))
endpoint = endpoint + ".asmx";
//OBJECT INSTANTIATION INSIDE THE METHOD
ret = new My_API.NextGenCodeGen.CodeGenerator() { Url = endpoint, UseDefaultCredentials = true};**
lock(branchGenLock)
{
branchGenerators[BranchId] = ret;
}
}
return ret;
}
}
示例 2-
public class CodeGenAPIController : ApiResponseController
{
//OBJECT INSTANTIATION OUTSIDE THE METHOD AT THE CLASS LEVEL
NextGenCodeGen.ARGenTCodeGenerator retVal = new My_API.NextGenCodeGen.ARGenTCodeGenerator();
NextGenCodeGen.CodeGenerator getEndPoint(TokenManager.TokenData tokenData, int BranchId)
{
retVal = null;
lock (branchGenLock)
{
if (branchGenerators.ContainsKey(BranchId))
retVal = branchGenerators[BranchId];
}
if (retVal == null)
{
string services = ConfigurationValuesAPIController.GetBranchProperties(tokenData.DatabaseIdentifier, BranchId).FirstOrDefault(x => x.Key == "AvailableCodeGenServices").Value;
string[] endpoints = services.Split(new char[] { ' ', '.' }, StringSplitOptions.RemoveEmptyEntries);
if (endpoints.Length == 0)
throw new ArgumentOutOfRangeException("AvailableCodeGenServices",
string.Format("There appear to be no Code Generation Services configured for branch {0}", BranchId));
string endpoint = endpoints[0];
if (!endpoint.ToLower().EndsWith(".asmx"))
endpoint = endpoint + ".asmx";
retVal = new My_API.NextGenCodeGen.CodeGenerator();
retVal.Url = endpoint;
retVal.UseDefaultCredentials = true;
lock (branchGenLock)
{
branchGenerators[BranchId] = retVal;
}
}
return retVal;
}
}
通过在 class 级别声明变量,您将其范围限定为 class 实例。即使您在函数中 re-initialize 它,它的作用域仍然在函数外部。根据 CA2000 文档,这不会触发警告,因为 "all references to it are out of scope" 不正确。
官方文档:https://msdn.microsoft.com/en-us/library/ms182289.aspx
由于在第一个示例中发出了警告,这应该表明 My_API.NextGenCodeGen.CodeGenerator
实现了 IDisposable
。如果为真,则考虑向此 class 添加一个 Dispose
处理程序并在那里执行任何 class-owned IDisposable
变量清理。垃圾收集器将处理其余部分。
如果您的 ApiResponseController
继承了 ApiController
,那么您已经拥有车辆,只需驾驶即可:
public abstract class ApiController : IHttpController, IDisposable
在 class 情况下,应该 跳闸 CA2213 而不是 CA2000。 https://msdn.microsoft.com/en-us/library/ms182328.aspx
CA2213 似乎有一个限制,它无法确定如何处理实现 IDisposable 的基础 classes。在下面的示例中,FileIo 继承自 IoBase 并且不会引发警告。 FileIo2 仅实现 IDisposable 并且 确实 引发警告。
public class IoBase : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
public class FileIo: IoBase
{
private Stream io = new FileStream("c:\tmp\tmp.txt", FileMode.OpenOrCreate);
}
public class FileIo2 : IDisposable
{
private Stream io = new FileStream("c:\tmp\tmp.txt", FileMode.OpenOrCreate);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
我正在为使用 .net 的 SPA 应用程序开发 Web Api。当我在方法中使用实例化对象时,我收到 CA2000 警告。但是当我在 class 级别声明相同的对象时,CA2000 警告消失了。从下面看,示例 1 给出了 CA2000 警告,而示例 2 没有。为什么?
示例 1-
public class CodeGenAPIController : ApiResponseController
{
NextGenCodeGen.CodeGenerator getEndPoint(TokenManager.TokenData tokenData, int BranchId)
{
NextGenCodeGen.CodeGenerator ret = null;
lock (branchGenLock)
{
if (branchGenerators.ContainsKey(BranchId))
ret = branchGenerators[BranchId];
}
if (ret == null)
{
string services = ConfigurationValuesAPIController.GetBranchProperties(tokenData.DatabaseIdentifier, BranchId).FirstOrDefault(x => x.Key == "AvailableCodeGenServices").Value;
string[] endpoints = services.Split(new char[] { ' ', '.' }, StringSplitOptions.RemoveEmptyEntries);
if (endpoints.Length == 0)
throw new ArgumentOutOfRangeException("AvailableCodeGenServices",
string.Format("There appear to be no Code Generation Services configured for branch {0}", BranchId));
string endpoint = endpoints[0];
if (!endpoint.ToLower().EndsWith(".asmx"))
endpoint = endpoint + ".asmx";
//OBJECT INSTANTIATION INSIDE THE METHOD
ret = new My_API.NextGenCodeGen.CodeGenerator() { Url = endpoint, UseDefaultCredentials = true};**
lock(branchGenLock)
{
branchGenerators[BranchId] = ret;
}
}
return ret;
}
}
示例 2-
public class CodeGenAPIController : ApiResponseController
{
//OBJECT INSTANTIATION OUTSIDE THE METHOD AT THE CLASS LEVEL
NextGenCodeGen.ARGenTCodeGenerator retVal = new My_API.NextGenCodeGen.ARGenTCodeGenerator();
NextGenCodeGen.CodeGenerator getEndPoint(TokenManager.TokenData tokenData, int BranchId)
{
retVal = null;
lock (branchGenLock)
{
if (branchGenerators.ContainsKey(BranchId))
retVal = branchGenerators[BranchId];
}
if (retVal == null)
{
string services = ConfigurationValuesAPIController.GetBranchProperties(tokenData.DatabaseIdentifier, BranchId).FirstOrDefault(x => x.Key == "AvailableCodeGenServices").Value;
string[] endpoints = services.Split(new char[] { ' ', '.' }, StringSplitOptions.RemoveEmptyEntries);
if (endpoints.Length == 0)
throw new ArgumentOutOfRangeException("AvailableCodeGenServices",
string.Format("There appear to be no Code Generation Services configured for branch {0}", BranchId));
string endpoint = endpoints[0];
if (!endpoint.ToLower().EndsWith(".asmx"))
endpoint = endpoint + ".asmx";
retVal = new My_API.NextGenCodeGen.CodeGenerator();
retVal.Url = endpoint;
retVal.UseDefaultCredentials = true;
lock (branchGenLock)
{
branchGenerators[BranchId] = retVal;
}
}
return retVal;
}
}
通过在 class 级别声明变量,您将其范围限定为 class 实例。即使您在函数中 re-initialize 它,它的作用域仍然在函数外部。根据 CA2000 文档,这不会触发警告,因为 "all references to it are out of scope" 不正确。
官方文档:https://msdn.microsoft.com/en-us/library/ms182289.aspx
由于在第一个示例中发出了警告,这应该表明 My_API.NextGenCodeGen.CodeGenerator
实现了 IDisposable
。如果为真,则考虑向此 class 添加一个 Dispose
处理程序并在那里执行任何 class-owned IDisposable
变量清理。垃圾收集器将处理其余部分。
如果您的 ApiResponseController
继承了 ApiController
,那么您已经拥有车辆,只需驾驶即可:
public abstract class ApiController : IHttpController, IDisposable
在 class 情况下,应该 跳闸 CA2213 而不是 CA2000。 https://msdn.microsoft.com/en-us/library/ms182328.aspx
CA2213 似乎有一个限制,它无法确定如何处理实现 IDisposable 的基础 classes。在下面的示例中,FileIo 继承自 IoBase 并且不会引发警告。 FileIo2 仅实现 IDisposable 并且 确实 引发警告。
public class IoBase : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
public class FileIo: IoBase
{
private Stream io = new FileStream("c:\tmp\tmp.txt", FileMode.OpenOrCreate);
}
public class FileIo2 : IDisposable
{
private Stream io = new FileStream("c:\tmp\tmp.txt", FileMode.OpenOrCreate);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}