Skip to content

Instantly share code, notes, and snippets.

@controlflow
Created December 5, 2013 13:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save controlflow/7804901 to your computer and use it in GitHub Desktop.
Save controlflow/7804901 to your computer and use it in GitHub Desktop.
How C# lambdas with a single ref-type immutable closure can be optimized
using System;
static class LiftingClosureToDelegateTarget {
static void Main() {
// normal lambda
{
var str = GetString();
Func<string> f = () => str;
Console.WriteLine(f());
}
// what is generated (two allocations: closure and delegate)
{
var closure = new Closure();
closure._str = GetString();
Func<string> f = new Func<string>(closure.LambdaBody);
Console.WriteLine(f());
}
// what CAN be generated if captured variable is immutable (single allocation: delegate)
// delegate instance contains both 'str' reference and a function pointer to static method
{
var str = GetString();
Func<string> f = new Func<string>(str.LambdaBodyAsExtensionMethod);
Console.WriteLine(f());
}
// the same with reflection
{
var str = GetString();
Func<string> f = (Func<string>) Delegate.CreateDelegate(
type: typeof (Func<string>),
firstArgument: str, // <-- all magic is here
method: typeof (LiftingClosureToDelegateTarget).GetMethod("LambdaBodyAsExtensionMethod"));
Console.WriteLine(f());
}
}
private static string GetString() {
return "abc";
}
private sealed class Closure {
public string _str;
public string LambdaBody() { return _str; }
}
public static string LambdaBodyAsExtensionMethod(this string str) {
return str;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment