类级变量与CA2000警告方法的区别

时间:2017-02-03 19:56:59

标签: c# asp.net .net asp.net-web-api dispose

我正在使用.net为一个SPA应用程序开发Web Api。当我使用实例化方法中的对象时,我收到CA2000警告。但是当我在类级别声明相同的对象时,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;
    }
 }

2 个答案:

答案 0 :(得分:0)

通过在类级别声明变量,您可以将其作用于类实例。即使您在函数中重新初始化它,它的范围仍然是函数的外部。根据CA2000文档,这不会触发警告,因为"所有对它的引用超出范围"不是真的。

官方文件:https://msdn.microsoft.com/en-us/library/ms182289.aspx

由于在第一个示例中发出了警告,这应该表明My_API.NextGenCodeGen.CodeGenerator实现了IDisposable。如果为true,则考虑在此类中添加Dispose处理程序,并在那里执行任何类拥有的IDisposable变量清理。垃圾收集将处理其余的事情。

如果您的ApiResponseController继承ApiController,那么您已经拥有了这辆车,那么您只需驾驶它:

public abstract class ApiController : IHttpController, IDisposable

答案 1 :(得分:0)

在课堂案例中,应该行程CA2213而不是CA2000。 https://msdn.microsoft.com/en-us/library/ms182328.aspx

看起来有一个CA2213的限制,它无法弄清楚如何处理实现IDisposable的基类。在下面的示例中,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)
    {
    }
}