繁体   English   中英

使用链式构造函数避免代码分析 CA2000 警告?

[英]Avoiding code analysis CA2000 warning with chained constructors?

避免 CA2000 警告关于 non-disposed locals 的正常模式是使用一个临时变量,如果出现任何问题,该变量就会被释放,例如:

Foo f = null;
try
{
    f = new Foo();
    Foo result = f;
    f = null;
    return result;
}
finally
{
    if (f != null)
    {
        f.Dispose();
    }
}

有点冗长,但它有效,而且很有意义。 但是如何将该模式应用于链式构造函数,如下所示:

public HomeController ( IDataRepository db )
{
    this.repo = db ?? new SqlDataRepository();
}

public HomeController ( )
    : this(new SqlDataRepository())
{
}

此代码抛出两个 CA2000 警告,每个构造函数一个。 第一个我可以摆脱使用临时变量模式。 这很烦人,因为在 scope 构建之后但在它被分配给成员字段之前,go 的本地没有任何方法,该字段稍后会被清理。 所以我不知道 CA 的问题是什么,但至少我知道如何解决它。

但是,据我所知,没有任何替代方法可以编写第二个构造函数调用来引入 try/finally。 分配给的字段是只读的,因此必须在构造函数中设置。 并且 C# 不会让您在任何地方调用链式构造函数,而是紧接在构造函数主体之前。 而且,在这两个警告中,第二个警告实际上是更合理的一个——对链式构造函数的调用可能(理论上,如果它确实做了任何实际工作)会引发异常,并使新构造的参数不被处理。

当然,我总是可以直接压制这条消息(CA2000 似乎需要很多),但如果有一种实际的方法可以消除这个问题,我更愿意这样做。

我无法在采用 IDataRepository 参数的构造函数上重现 CA2000 违规。 鉴于此,以及您对两个构造函数使用相同的“默认值”这一事实,在示例场景中避免 CA2000 问题的最简单更改是:

public HomeController(IDataRepository db)
{
    this.repo = db ?? new SqlDataRepository();
}

public HomeController()
    : this(null)
{
}

显然,如果您的第一个构造函数不接受 null 参数值,这将无法正常工作。 如果是这种情况,并且您完全同意仅在一个位置设置相应字段的想法,那么您仍然可以选择避免 CA2000,例如调用更智能的私有构造函数。 例如:

public HomeController(IDataRepository db)
    : this(() => db, false)
{
    if (db == null)
    {
        throw new ArgumentNullException("db");
    }
}

public HomeController()
    : this(() => new SqlDataRepository(), true)
{
}

private HomeController(Func<IDataRepository> repositoryRetriever, bool disposeOnFailure)
{
    IDataRepository repository = repositoryRetriever.Invoke();
    try
    {
        this.repo = repository;
    }
    catch
    {
        if (disposeOnFailure)
        {
            repository.Dispose();
        }

        throw;
    }
}

就我个人而言,我认为以上内容是非常讨厌的 hack,特别是考虑到它涉及增加代码复杂性和运行时异常的机会,以避免一开始并不严重的潜在问题。 我的建议是简单地忽略此类潜在的 CA2000 违规行为,除非以下两个都成立:

  1. 在 object 的实例化和将其分配给字段的方法结束之间确实有可能发生非崩溃异常。
  2. 未能处理孤立实例的后果是相当严重的(例如:锁定文件)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM