簡體   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