2011-07-06 15 views
1

これは失敗しますか? Resharperはこれを「変更されたクロージャへのアクセス」のインスタンスとして報告します ラムダはあらゆる値に対してトリガーされますか? firstの行が実行される前に、イテレータがすべての間隔値の完全なリストをthisに生成していますか?または、リーチ反復のために行first = itvl; が実行されていて、その後の反復のために使用されたfirstの値が変更されましたか?変更されたクロージャへのアクセス

public HourInterval FirstInterval 
    { 
     get 
     { 
      var first = HourInterval.Make(DateTime.MaxValue); 
      foreach (var itvl in this.Where 
         (itvl => itvl < first)) 
       first = itvl; 
      return first; 
     } 
    } 

注意。 HourIntervalは、各時間長カレンダー時間を表す値型の構造体であり、...とthisHourIntervalオブジェクト

EDITのIEnumerable集合である:

上記Resharperのは、LINQに変換することが示唆ものです以下foreach建設からの発現は...

public HourInterval FirstInterval 
    { 
     get 
     { 
      var first = HourInterval.Make(DateTime.MaxValue); 
      foreach (var itvl in this) 
       if(itvl < first) 
        first = itvl; 
      return first; 
     } 
    } 
+0

あなたは 'return this.Min(itvl);'を実行できませんでしたか? – Carson63000

+1

@Carson:いいえ、できません。 – SLaks

答えて

14

を試してみてください。

まず、同じコード内で2つのやや矛盾した方法で同じ変数名を使用するのは、プログラミングの習慣としては貧弱です。それは非常に混乱しています。率直に言って、私はこれが違法であることを好むでしょう。それが違法でない理由は少し複雑です。詳細はhttp://blogs.msdn.com/b/ericlippert/archive/2009/11/05/simple-names-are-not-so-simple-part-two.aspxを参照してください。

のは、その問題を取り除くしてみましょう:

var first = HourInterval.Make(DateTime.MaxValue); 
foreach (var itvl in this.Where(x => x < first)) 
    first = itvl; 

、次の質問は次のとおりです。ReSharperのは、これが修正閉鎖へのアクセスであることに注意することが正しいのですか?はい、Resharperは正しいです。繰り返し呼び出されるラムダのクローズドオーバー変数を変更しています。 Resharperは、Resharperは "Where"が何をしているのか分からないので、これは危険であると指摘しています。すべてのResharperが知っているところでは、 "Where"は各述語がキャッシュされ、後で実行するためにそれを保存しています。実際には、各述語は同じ変数で閉じられるのではなく、同じ述語が同じ変数上で閉じられるため、同じです。

明らかに「Where」の賢明な実装はそれを行いません。しかし、Resharperはそれを知らない。

次の質問です。これは分かりやすいことですか?いいえ。これは、述語のクローズドオーバー変数を「場所」に変更することによって、「Min」を実装するために非常にユニートリマーで混乱する方法です。あなたは分を書きたい場合は、単に分を記述します。シーケンスが空の場合

あり
static DateTime? Min(this IEnumerable<DateTime> seq) 
{ 
    DateTime? min = null; 
    foreach(DateTime current in seq) 
    { 
     if (min == null || current < min.Value) 
      min = current; 
    } 
    return min; 
} 

、それが早い順に、日付、またはnullを返します。どこでも述語や突然変異したクロージャーとそのナンセンスに悩まされることはありません。コードを簡単で正確に書いてください。

+0

エリック、私は本当にLINQ /ラムダ語学者ではないと告白します..Resharperが私が始めた標準的なforeach()アプローチを変えたのは、あなたが見たものです(私が編集で見たもので始まったこと以外は何を示唆しているのと同様です)。 min = null ...最適なコードスニペットを見つけようとしていませんが、私はlamdasの動作の仕方を尋ねています。この「変更されたクロージャへのアクセス」エラーに注意する必要がありますか? msg、あなたは私の質問に答えてくれました...ありがとう、 'Where(x => x

10

あなたのコードは動作するはずですが、それはそれを行うには、不必要に複雑な方法です。

はOK、これが混乱のビットです

this.Aggregate((min, next) => next < min ? next : min); 
関連する問題