[英]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.