C#のベースコンストラクターへのCA2000パスオブジェクト参照
-
30-09-2019 - |
質問
Visual Studioのコード分析ユーティリティを使用してコードを実行すると、解決方法がわかりません。おそらく、ここの誰かが同様の問題に出くわし、それを解決し、彼らの洞察を喜んで共有することをいとわないでしょう。
DatagridViewコントロールで使用されるカスタム塗装セルをプログラミングしています。コードは次のとおりです。
public class DataGridViewMyCustomColumn : DataGridViewColumn
{
public DataGridViewMyCustomColumn() : base(new DataGridViewMyCustomCell())
{
}
次の警告を生成します。
CA2000:Microsoft.Reliability:Method 'datagridviewmycustomcolumn.datagridviewmycustomcolumn()' call system.idisposable.dispose 'new datagridviewmycustomcell()' 'のすべての参照が範囲外になる前に。
DatagridViewmycustomcell(またはそれが継承するクラス)が特徴的なインターフェイスを実装していることを警告していることを理解しており、DatagridViewmycustomcellが請求されたリソースがなくなった場合は、dispose()メソッドを呼び出す必要があります。
インターネットで見た例は、ブロックを使用してオブジェクトの寿命を節約し、システムを自動的に処分させることを示唆していますが、コンストラクターの本体に移動したときにベースは認識されないため、使用することはできません。それをブロックする...とにかくやりたいとは思わない。
私の質問では、コードは大丈夫ですか?または、警告を解決するためにどのようにリファクタリングできますか?それを行うことが本当に適切でない限り、私は警告を抑制したくありません。
解決
Visual Studio 2010を使用している場合、CA2000は完全に壊れています。また、FXCOP(別名コード分析)の他のバージョンでも壊れている可能性がありますが、VS2010は私が保証できる唯一のものです。私たちのコードベースは、このようなコードに対してCA2000警告を与えています...
internal static class ConnectionManager
{
public static SqlConnection CreateConnection()
{
return new SqlConnection("our connection string");
}
}
...メソッドの範囲外になる前に接続が処分されていないことを示します。まあ、ええ、それは本当ですが、それは範囲外ではありません アプリケーション用 発信者に返されると、それがメソッドの全体的なポイントです!同様に、コンストラクターの引数は範囲外ではなく、基本クラスに渡されているため、実際の問題ではなく、ルールから誤った陽性です。
これは以前は有用なルールでしたが、今では本当にできることは、彼らがそれを修正するまでそれをオフにすることだけです。 (非常に少ない)実際のポジティブなものは修正すべきものだからです。
他のヒント
チェーンズコンストラクターに新しいものをパスする安全でエレガントな方法はありません IDisposable
あなたが注意するように、チェーンズコンストラクターの呼び出しをいかなる種類でも包むことはできないので、ベースコンストラクターに反対します try finally
ブロック。安全なアプローチがありますが、それはほとんどエレガントではありません。ユーティリティ方法を定義します。
internal static TV storeAndReturn<TR,TV>(ref TR dest, TV value) where TV:TR
{
dest = value; return value;
}
コンストラクターに次のように見えます。
protected DataGridViewMyCustomColumn(ref IDisposable cleaner) :
base(storeAndReturn(ref cleaner, new DataGridViewMyCustomCell()))
{
}
新しいオブジェクトが必要なコードは、適切なコンストラクターを呼び出すpublic static Factoryメソッドを呼び出す必要があります。 try
/finally
メインラインが無効になるブロック cleaner
それが終了する直前、そして誰が finally
ブロックが呼び出されます Dispose
の上 cleaner
nullでない場合。すべてのサブクラスが同様の工場メソッドを定義している場合、このアプローチにより、新しいアプローチが保証されます IDisposable
オブジェクトは、作成された時間と、カプセル化オブジェクトがクライアントコードにさらされるまでの時間の間に例外が発生した場合でも廃棄されます。パターンは醜いですが、他のより良いパターンが正確さを保証するかどうかはわかりません。