I have the following code:
string prefix = "OLD:";
Func<string, string> prependAction = (x => prefix + x);
prefix = "NEW:";
Console.WriteLine(prependAction("brownie"));
Because the compiler replaces the prefix variable with a closure "NEW:brownie" is printed to the console.
Is there an easy way to prevent the compiler from lifting the prefix variable whilst still making use of a lambda expression? I would like a way of making my Func work identically to:
Func<string, string> prependAction = (x => "OLD:" + x);
The reason I need this is I would like to serialize the resulting delegate. If the prefix variable is in a non-serializable class the above function will not serialize.
The only way around this I can see at the moment is to create a new serializable class that stores the string as a member variable and has the string prepend method:
string prefix = "NEW:";
var prepender = new Prepender {Prefix = prefix};
Func<string, string> prependAction = prepender.Prepend;
prefix = "OLD:";
Console.WriteLine(prependAction("brownie"));
With helper class:
[Serializable]
public class Prepender
{
public string Prefix { get; set; }
public string Prepend(string str)
{
return Prefix + str;
}
}
This seems like a lot of extra work to get the compiler to be "dumb".
I see the underlying problem now. It is deeper than I first thought. Basically the solution is to modify the expression tree before serializing it, by replacing all subtrees that do not depend on the parameters with constant nodes. This is apparently called "funcletization". There is an explanation of it here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With