避免CA2000警告未处理的本地人的正常模式是使用临时变量,如果出现任何问题就会被处置,例如:
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警告,每个构造函数一个。第一个我可以摆脱使用临时变量模式。这很烦人,因为在构建之后,但是在它被分配到成员字段之前,本地没有任何方式让它超出范围,之后会被清除。所以我不知道CA的问题是什么,但至少我知道如何解决它。
但是,据我所知,没有任何其他方法可以编写第二个构造函数调用来引入try / finally。分配给的字段是只读的,因此必须在构造函数中设置。并且C#不会让你在构造函数体之前的任何地方调用链式构造函数。而且,在这两个中,第二个警告实际上是更合法的一个 - 对链式构造函数的调用(理论上,如果它做了任何实际工作)抛出一个异常并使新构造的参数不被暴露。
当然,我总是可以压制这个消息(CA2000似乎需要很多),但如果有一种实际的方法可以消除这个问题,我宁愿这样做。
答案 0 :(得分:2)
我无法在带有IDataRepository参数的构造函数上重现CA2000违规。鉴于此,以及对两个构造函数使用相同的“默认”这一事实,最简单的更改将避免样本方案的CA2000问题:
public HomeController(IDataRepository db)
{
this.repo = db ?? new SqlDataRepository();
}
public HomeController()
: this(null)
{
}
显然,如果您的第一个构造函数不接受null参数值,这将无法正常工作。如果是这种情况,并且您完全同意只在一个地方设置相应字段的想法,您仍然可以选择避免使用CA2000,例如调用稍微更智能的私有构造函数。 e.g:
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;
}
}
就我个人而言,我认为以上是非常讨厌的黑客,特别是考虑到它涉及增加代码复杂性和运行时异常的机会,以避免一开始就不是很严重的潜在问题。我的建议是简单地忽略此类潜在的CA2000违规,除非以下两种情况都成立: