3

私が以下を持っている場合:

static readonly TimeSpan ExpiredAfter = TimeSpan.FromMilliseconds(60000);

foreach (ModuleInfo info in moduleList.Where(i => DateTime.Now - i.LastPulseTime > ExpiredAfter).ToArray())
    moduleList.Remove(info);

ExpiredAfterは解除されますか、それともコンパイラは直接アクセスできることを知っていますか?このように書く方が効率的でしょうか:

static readonly TimeSpan ExpiredAfter = TimeSpan.FromMilliseconds(60000);

static bool HasExpired(ModuleInfo i) { return DateTime.Now - i.LastPulseTime > ExpiredAfter; }

foreach (ModuleInfo info in moduleList.Where(HasExpired).ToArray())
    moduleList.Remove(info);
4

2 に答える 2

1

ExpiredAfterは解除されますか、それともコンパイラは直接アクセスできることを知っていますか?

確認する最も簡単な方法は、コードをコンパイルしてから、Reflectorなどで逆コンパイルすることです。コンパイラは、静的変数に直接アクセスする静的メソッドを生成するだけだと思います。

このように書く方が効率的でしょうか:

繰り返しになりますが、自分でテストしてください:)そのように書く方が効率的だったとしても必ずしも正しい選択になるとは限りませ。どちらが読みやすいですか?この小さなコードは、パフォーマンスにとってどれほど重要ですか?もう十分速いですか?

于 2012-07-02T17:00:06.733 に答える
1

静的な(または、さらに言えば、任意の)フィールドをキャプチャできない可能性があります。

言語仕様から:

7.15.5外部変数スコープにラムダ式またはanonymous-method-expressionが含まれるローカル変数、値パラメーター、またはパラメーター配列は、無名関数の外部変数と呼ばれます。クラスのインスタンス関数メンバーでは、 this値は値パラメーターと見なされ、関数メンバー内に含まれる無名関数の外部変数です。

7.15.5.1キャプチャされた外部変数外部変数が無名関数によって参照されている場合、外部変数は無名関数によってキャプチャされたと言われます。

静的フィールドは、ローカル変数、値パラメーター、またはパラメーター配列になることはありません。

とはいえ、コンパイラが理由もなくキャプチャする奇妙なコーナーケースをいくつか見ましthisたが、これはその1つではないようです。インスタンスと静的囲みメソッドの両方の場合、ラムダ用にC#4.0コンパイラによって生成されたコードは、コンパイラが次のように見えることを除いて、 「手動」バージョンとほとんど同じであることを逆コンパイラで確認しました。ラムダの場合にのみ、結果のデリゲートへの参照を(静的フィールドで)キャッシュして再利用します。これにより、この場合(囲んでいるメソッドを複数回実行する場合)、メソッドグループの方法よりもラムダの方法が高速になります(メモリの負荷が少なくなります)。ただし、確実に見つけるには、両方の方法でベンチマークを行う必要があります...

于 2012-07-02T17:28:23.870 に答える