4

If I have the following:

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

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

Does ExpiredAfter get lifted or does the compiler know it can access it directly? Would it be more efficient to write it like this:

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);
Tergiver
  • 14,171
  • 3
  • 41
  • 68

2 Answers2

2

A static (or for that matter, any) field can't possibly be captured.

From the language spec:

7.15.5 Outer variables Any local variable, value parameter, or parameter array whose scope includes the lambda-expression or anonymous-method-expression is called an outer variable of the anonymous function. In an instance function member of a class, the this value is considered a value parameter and is an outer variable of any anonymous function contained within the function member.

7.15.5.1 Captured outer variables When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function.

A static field is never a local variable, a value parameter or parameter array.

That said, I've seen some strange corner cases where the compiler captures this without reason, but this doesn't seem to be one of those. I verified with a decompiler that both in the case of an instance and static enclosing method, the code generated by a C# 4.0 compiler for the lambda is pretty much the same as your 'manual' version... except that the compiler appears to be caching and reusing a reference to the resulting delegate (in a static field) only for the lambda case. This could counterintuitively make the lambda way faster (and add less memory pressure) than the method-group way in this case (over multiple executions of the enclosing method)! You'll have to benchmark it both ways to find out for sure though...

Community
  • 1
  • 1
Ani
  • 111,048
  • 26
  • 262
  • 307
1

Does ExpiredAfter get lifted or does the compiler know it can access it directly?

The easiest way to check is to compile your code and then decompile it in Reflector or the like. I would expect the compiler to just generate a static method which accesses the static variable directly.

Would it be more efficient to write it like this:

Again, test it yourself :) Even if it were more efficient to write it that way, that wouldn't make it necessarily the right choice. Which is more readable for you? How performance-critical is this little bit of code? Is it already fast enough?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194