Today I faced a SerializationException that refered to some anonymous inner class stating it was not serializable, when IIS tried to store the session in the ASP.NET State Service:
Type ‘Xyz+<>c__DisplayClass10′ in Assembly ‘Xyz, Version=1.2.5429.24450, Culture=neutral, PublicKeyToken=null’ is not marked as serializable.
I looked for lambdas in my code and found quite a few, but most of them were not new and did never have any issues in serialization. But then I noticed that I had built in a new lambda expression that “happened” to build up a closure.
I have built a very simple example to confirm that closures are not serializable whereas “normal” functions are:
[TestFixture]
public class GeneralUnderstandingTests
{
[Serializable]
private class ASerializableType
{
private readonly Func thisIsAClosure;
private readonly Func thisIsNotAClosure;
public ASerializableType()
{
// Normal functions are allowed: The following
// succeeds to serialize
const int SomeConst = 12345;
thisIsNotAClosure = () => SomeConst;
// But closures are compiled to non-serializable
// inner classes and break serialization:
var someVariable = 12345;
thisIsAClosure = () => someVariable;
}
}
[Test]
public void ASerializableType_CanBeSerialized()
{
var sessionState = SessionStateItemCollection();
sessionState["sut"] = new ASerializableType();
sessionState.Serialize(
new BinaryWriter(new MemoryStream()));
}
}
This test fails but goes green as soon as the line thisIsAClosure = … is commented out. The line thisIsNotAClosure = … however does not cause any issues as SomeConst is not a variable but a constant, that is, it does not build a closure but is inlined by the compiler.