2010-11-19 12 views
2

このコードスニペットを考える:それがあるべきとして宣言リストchangedRowsとラインの前にVS2008デバッガは範囲外のオブジェクトを保持していますか?

// Get first key // 
int? keyEDISecurity = this.WorkQueue.GetNextWorkItem(); 

// Done? // 
while (keyEDISecurity != null) 
{ 
    try 
    { 

     ... 

     // Write changes // 
     List<ISNLEditableObject> changedRows = this.WorkQueue.GetChangedRows((int)keyEDISecurity); 
     this.Writer.Write(changedRows, WriteFlags.Transactional); 

     ... 
    } 
    catch (Exception ex) 
    { 
     // Exception handling/logging code 
    } 
    finally 
    { 
     // Remove all data for the KeyEDISecurity from work queue cache // 
     this.WorkQueue.RemoveData((int)keyEDISecurity); 
    } 

    // Get next work item // 
    keyEDISecurity = this.WorkQueue.GetNextWorkItem(); 
} 

を、changedRowsは、nullです。次に、次の作業項目を取得すると、範囲外になります。そして、同じ行の前で、changedRowsにアクセスすると、宣言されていないので、再びnullになります。

ブレークして編集すると、期待通りに、範囲外になっており、まだ宣言されていないため、changedRowsにアクセスできません。これを評価すると(マウスオーバーまたは直接ウィンドウを使用して)、ループの以前の反復からchangedRowsにアクセスできます。 WTH?

誰でもこれを見ましたか?それはコードでは正しく動作するように見えるので、プログラムには影響しませんが、デバッガの問題は予想通りに動作していなかったので時間の無駄です。私はこれが期待された行動かどうか疑問に思っていたので、将来私が知ることができ、時間を無駄にすることはできませんでした。

答えて

6

これは実装固有の最適化です。

関数が実行されると、すべての変数は通常、一度にスタック上に作成されます。言語はまだそれらにアクセスすることを許可していませんが、そこにあります。そのため、宣言される前にchangedRowsnullとなっています。

変数が有効範​​囲外になると、その言語では変数を再び使用することはできませんが、スタックにはまだそのままです。その値はnullに変更する必要はありません。これはどこでも使用されないためです。プロセッサ時間が無駄になります。これは、言語規則に従って、(スコープから外れると)破棄され、(宣言されたときに)再度作成されなければならないのに、changedRowsの値が保持される理由です。

デバッガはすべての言語ルールを遵守していません。実際、それはいくつかの構造によって混乱することさえあるかもしれません。変数の値を取得しようとすると、デバッガはスコープ内にあるかどうかをチェックしません。

関連する問題