2016-05-13 69 views
1

私はこの警告を抑制せずに対処しようとしています。それを個人的な挑戦と呼んでください。それへのすべての参照がスコープ外になる前にCA2000の仕組みとその回避策

方法で

CA2000CreateAndUseは」、「新しいプロジェクト()」オブジェクトにSystem.IDisposable.Disposeを呼び出します。

IDisposableとすると、任意のProjectクラスのインターフェイス。

public static TR Using<T, TR>(this T instance, Func<T, TR> expression) 
    where T : IDisposable 
{ 
    using (instance) 
     return expression(instance); 
} 

確かにスマートコンパイラはこれを正しく分析することができる必要があります:拡張メソッドを考える

public void CreateAndUse() 
{ 
    var instances = new Project().Using(_ => _.LoadItems()); 
} 

? CA2000が発生
私は何かが足りないと思う...

+2

あなたの拡張メソッドが 'using'ステートメントを使ってあなたに与える価値は?それはほんの数文字未満のコードですか?他の開発者がインダイレクションの層に感謝すると思いますか?コードを読みやすく理解していますか?これはナンセンスです。 – jgauffin

+1

'CA2000'はコンパイラエラーではなく、コード解析エラーです。コード分​​析は、コードが正しいことを確実に実行していることを証明するために網羅的なフロー分析を実行するように設計されておらず、ここでやっている問題のあるコードパターンを検出するためにかなり簡単な分析を行うように設計されています。 「使い捨てオブジェクトは範囲外になる前に処分されるべきです」は、「この特定のプログラムで実行可能なすべてのパスが確実に '.Dispose()'が呼び出されることを確認する」よりも実装が少し簡単です。一般に。 –

+0

最後のコメントには実際に答えがあります。 QUESTIONは、「スマートなコンパイラがこれを正確に分析できるはずですか? CA2000は全くコンパイラと無関係です。 – TomTom

答えて

1

あなたが実際に聞いて一つの質問は次のとおりです。

確かにスマートコンパイラはこれを正しく解析することができるはずですか?

これは基本的な誤解を示しています。 CA2000はコンパイラの問題ではありません。これはコード解析の問題であり、コンパイラとは完全に別です。そして、それは「かなり」スマートではありません。コンパイラはこれに関与していないので、ここでは何もできません。

このCAを処理する適切な方法は、それを見て、それが関連しているかどうかを判断し、可能であればその方法で抑止することです。

理由は?

作成されたオブジェクトを処理したり処理したりすることはしばしば誤りですが、目的の機能であることがあります。返されたオブジェクトがすでに破棄されている場合、ファクトリメソッド(GetDatabaseConnection())はまったく役に立たないでしょう。

しかし、これらは「エッジ」のケースです。プログラマは、警告が表示されると決定できます。これはメソッドレベルの抑制のためのものです。

この場合、同様の(しかし同じではありませんが)例については、How to get rid of CA2000 warning when ownership is transferred?を参照してください。

+0

私の意見では、すべての解析をroslynコンパイラで利用できるので、これをより良く検出できるはずです。 '/ analyze'は実際には[コンパイラオプション](https://msdn.microsoft.com/en-us/library/ms173498.aspx)です... – Jim

+0

コンパイラOPTIONですが、コンパイラにはありません。あなたは分析のために読んでいらっしゃいましたか?彼らは外部です。最初に、あなたは実際に新しいものを使いますか? (https://www.nuget.org/packages/Microsoft.CodeAnalysis)?はい、Roslynはそれをより良くすることができますが、あなたが分析をインストールするまで...そして、それでもなお:座って修正してください) – TomTom

+0

jeepers、あなたが尋ねたので、確かに:私はroslynコードanlaysisプラグインを書いて、アナライザを使用し、何年もの間コンパイラを書いていたので、私はその話題について少しは知っています。この質問に関連するコード分析について私を修正してくれてありがとう。とても有難い。 – Jim

1

理由は無地でシンプルです:あなたは、あなたのCreateAndUse()方法に配置されていないIDisposableへの参照を持っています。

あなたの拡張メソッドがあなたのオブジェクトを処分するという事実は無関係です。コードアナライザーは、拡張メソッドが実行されるまでにインスタンスが破棄されることは保証されません。 usingブロックの外にある拡張メソッド内のオブジェクトで他のものをやってしまうとどうなりますか?他のものが例外を引き起こす場合(usingブロックを到達不能にする)そして、突然、不在のオブジェクトが周囲に横たわっています。それがCA2000があなたを守ろうとしていることです。他に何もない場合、コードアナライザーは、コードがおそらく失敗する可能性がある他のすべての方法を予測するのに十分なほどスマートです。

You can choose to suppress this warningブロックがIDisposableブロックであることを保証できない場合は、このような警告が表示されなくても問題がないことを示しています。一方、CA2000を抑止することなくCA2000を処理する最良の方法は、最初にCA2000が起きるのを防ぐことです。あなたが見ることができるように、Projectの範囲はちょうど1 usingブロックに絞られ

public void CreateAndUse() 
{ 
    List<Item> instances; 

    using (var p = new Project()) 
     instances = p.LoadItems(); 
} 

:そしてことを行うための最善の方法は、ただ直接それが使用されることを意図された方法をusingを使用することです。かなり明確です。 jgauffinは言ったように、間接的な層を追加する必要はありません。

+0

しかし、実際には、この種のケースを処理するには解析エンジン*をスマートにでき、スマートにすることはできませんでした。しかし、非常に狭いですが、if文がスパナを投げ捨てることは、おそらくユーザビリティの辺縁事例であることを意味します。 –

+0

@Lasse V. Karlsen:やあ、そうだと思います。私はこの別の方法について考え終わった(私の編集を参照)。 – BoltClock