[英]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 違規行為,除非以下兩個都成立:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.