あなたの建設の契約は満たされていません。オブジェクトのフィールド(this.data)を参照しているため、他のスレッドがフィールドにアクセスし、その値をAssumeと最初のパラメーターの解像度および3番目のパラメーターの解像度の間で変更する場合があります。(ei、それらは3つの完全に異なるアレイである可能性があります。)
配列をローカル変数に割り当ててから、メソッド全体でその変数を使用する必要があります。次に、他のスレッドが参照を変更する機能を持たないため、アナライザーは制約が満たされていることを認識します。
var localData = this.data;
if (localData == null) return;
byte[] newData = new byte[localData.Length]; // Or whatever the datatype is.
Array.Copy(localData, newData, localData.Length); // Now, this cannot fail.
これには、制約を満たすだけでなく、実際には、多くの場合、コードをより堅牢にするという追加の利点があります。
これがあなたの質問への答えにつながることを願っています。静的チェッカーを含むバージョンのVisualStudioにアクセスできないため、実際に直接質問に答えることはできませんでした。(私はVS2008 Proを使用しています。)私の答えは、コードの私自身の目視検査が結論するものに基づいており、静的コントラクトチェッカーは同様の手法を使用しているようです。私は困惑しています!そのうちの1つを入手する必要があります。:-D
更新:(従うべき多くの憶測)
振り返ってみると、(静的チェッカーにアクセスしなくても)証明できるものとできないものをかなり正確に推測できると思います。他の回答で述べられているように、静的チェッカーは手続き間分析を行いません。したがって、(OPのように)マルチスレッド変数アクセスの可能性が迫っているため、静的チェッカーはローカル変数(以下に定義)のみを効果的に処理できます。
「ローカル変数」とは、他のスレッドからアクセスできない変数を意味します。これには、メソッドで宣言された変数、またはパラメーターとして渡された変数が含まれます。ただし、パラメーターがref
orで装飾されてout
いるか、変数が匿名メソッドでキャプチャされている場合を除きます。
ローカル変数が値型の場合、そのフィールドもローカル変数です(再帰的になど)。
ローカル変数が参照型の場合、フィールドではなく、参照自体のみをローカル変数と見なすことができます。これは、メソッド内で構築されたオブジェクトにも当てはまります。コンストラクター自体が、構築されたオブジェクトへの参照をリークする可能性があるためです(たとえば、キャッシュ用の静的コレクションなど)。
静的チェッカーが手続き間分析を行わない限り、上記で定義されたローカルではない変数について行われた仮定はいつでも無効になる可能性があるため、静的分析では無視されます。
例外1:文字列と配列はランタイムによって不変であることがわかっているため、文字列または配列変数自体がローカルである限り、それらのプロパティ(長さなど)は分析の対象になります。これには、他のスレッドによって変更可能な配列の内容は含まれません。
例外2:配列コンストラクターは、構築された配列への参照をリークしないことがランタイムによって認識されている場合があります。したがって、メソッド本体内で構築され、メソッドの外部にリークされない(別のメソッドにパラメーターとして渡される、非ローカル変数に割り当てられるなど)配列には、ローカル変数と見なされる可能性のある要素が含まれます。
これらの制限はかなり厄介なようで、これを改善できるいくつかの方法を想像できますが、何が行われたのかわかりません。理論的には、静的チェッカーで実行できる他のいくつかのことがあります。それを手元に置いている人は、何が行われ、何が行われていないかを確認する必要があります。
- コンストラクターがオブジェクトまたはそのフィールドへの参照をリークしていないかどうかを判断し、そのように構築されたオブジェクトのフィールドをローカル変数と見なすことができます。
- メソッドに渡された参照型が、そのメソッドの呼び出し後もローカルと見なすことができるかどうかを判断するために、他のメソッドでリークなしの分析を行うことができます。
- ThreadStaticまたはThreadLocalで装飾された変数は、ローカル変数と見なすことができます。
- リフレクションを使用して値を変更する可能性を無視するオプションを指定できます。これにより、参照型のプライベート読み取り専用フィールドまたは静的プライベート読み取り専用フィールドを不変と見なすことができます。また、このオプションを有効にすると、構造内でのみアクセスされ、リークされないプライベート変数または内部変数Xをローカル変数
lock(X){ /**/ }
と見なすことができます。ただし、これらのことは事実上、静的チェッカーの信頼性を低下させるので、それはちょっと不確かです。
多くの新しい分析を開く可能性のある別の可能性は、変数とそれらを使用するメソッド(および再帰的になど)を特定の一意のスレッドに宣言的に割り当てることです。これは言語への主要な追加ですが、それだけの価値があるかもしれません。